call: add connecting animation
Brings a pulse animation on contact avatar while calling
Clears wrong layout instructions and use ButterKnife for views
injections.
We use a different layout file in landscape to better use the available
screen estate.
Change-Id: Ie40f64bc8951b29cfc2c6b1c7640e05de149ccf9
Tuleap: #834
diff --git a/ring-android/app/build.gradle b/ring-android/app/build.gradle
index 2b94327..9408560 100644
--- a/ring-android/app/build.gradle
+++ b/ring-android/app/build.gradle
@@ -21,6 +21,7 @@
compile 'com.google.zxing:core:3.2.1'
compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
compile 'com.jakewharton:butterknife:8.1.0'
+ compile 'com.skyfishjy.ripplebackground:library:1.0.1'
apt 'com.jakewharton:butterknife-compiler:8.1.0'
}
diff --git a/ring-android/app/src/main/java/cx/ring/client/CallActivity.java b/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
index 71b1518..e3765fc 100644
--- a/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
@@ -58,7 +58,7 @@
import static cx.ring.service.LocalService.Callbacks;
-public class CallActivity extends AppCompatActivity implements Callbacks, CallFragment.Callbacks, CallProximityManager.ProximityDirector {
+public class CallActivity extends AppCompatActivity implements Callbacks, CallFragment.ConversationCallbacks, CallProximityManager.ProximityDirector {
static final String TAG = CallActivity.class.getSimpleName();
public static final String ACTION_CALL = BuildConfig.APPLICATION_ID + ".action.call";
@@ -96,7 +96,7 @@
setContentView(R.layout.activity_call_layout);
- mMainView = findViewById(R.id.maincalllayout);
+ mMainView = findViewById(R.id.main_call_layout);
mMainView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -135,6 +135,12 @@
showSystemUI();
}
+ // Reload a new view
+ FragmentManager fragmentManager = getFragmentManager();
+ FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
+ mCurrentCallFragment = new CallFragment();
+ fragmentTransaction.replace(R.id.main_call_layout, mCurrentCallFragment).commit();
+
super.onConfigurationChanged(newConfig);
}
@@ -249,7 +255,7 @@
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
mCurrentCallFragment = new CallFragment();
- fragmentTransaction.add(R.id.maincalllayout, mCurrentCallFragment).commit();
+ fragmentTransaction.add(R.id.main_call_layout, mCurrentCallFragment).commit();
hideSystemUI();
}
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
index b6a0a78..8f31c97 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
@@ -37,6 +37,7 @@
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
+import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v7.app.ActionBar;
import android.text.Editable;
@@ -50,7 +51,6 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
@@ -61,9 +61,14 @@
import android.widget.TextView;
import android.widget.ViewSwitcher;
+import com.skyfishjy.library.RippleBackground;
+
import java.lang.ref.WeakReference;
import java.util.HashMap;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
import cx.ring.R;
import cx.ring.adapters.ContactPictureTask;
import cx.ring.client.ConversationActivity;
@@ -81,7 +86,7 @@
public class CallFragment extends Fragment implements CallInterface {
- static private final String TAG = CallFragment.class.getSimpleName();
+ static final private String TAG = CallFragment.class.getSimpleName();
public static final int REQUEST_TRANSFER = 10;
@@ -90,38 +95,65 @@
// Screen wake lock for incoming call
private WakeLock mScreenWakeLock;
- private View contactBubbleLayout;
- private ImageView contactBubbleView;
- private TextView contactBubbleTxt;
- private TextView contactBubbleNumTxt;
- private View acceptButton;
- private View refuseButton;
- private View hangupButton;
- private View securityIndicator;
+
+ @BindView(R.id.contact_bubble_layout)
+ View contactBubbleLayout;
+
+ @BindView(R.id.contact_bubble)
+ ImageView contactBubbleView;
+
+ @BindView(R.id.contact_bubble_txt)
+ TextView contactBubbleTxt;
+
+ @BindView(R.id.contact_bubble_num_txt)
+ TextView contactBubbleNumTxt;
+
+ @BindView(R.id.call_accept_btn)
+ View acceptButton;
+
+ @BindView(R.id.call_refuse_btn)
+ View refuseButton;
+
+ @BindView(R.id.call_hangup_btn)
+ View hangupButton;
+
+ @BindView(R.id.call_status_txt)
+ TextView mCallStatusTxt;
+
+ @BindView(R.id.security_indicator)
+ View securityIndicator;
+
+ @BindView(R.id.security_switcher)
+ ViewSwitcher mSecuritySwitch;
+
+ @BindView(R.id.dialpad_edit_text)
+ EditText mNumeralDialEditText;
+
+ @BindView(R.id.ripple_animation)
+ RippleBackground mPulseAnimation;
+
+ @BindView(R.id.video_preview_surface)
+ SurfaceView mVideoSurface = null;
+
private MenuItem speakerPhoneBtn = null;
private MenuItem addContactBtn = null;
private MenuItem flipCameraBtn = null;
private MenuItem dialPadBtn = null;
- private SurfaceView video = null;
- private SurfaceView videoPreview = null;
- ViewSwitcher mSecuritySwitch;
- private TextView mCallStatusTxt;
+ @BindView(R.id.camera_preview_surface)
+ SurfaceView videoPreview = null;
- public Callbacks mCallbacks = sDummyCallbacks;
+ public ConversationCallbacks mCallbacks = sDummyCallbacks;
private AudioManager audioManager;
-
private boolean haveVideo = false;
private int videoWidth = -1, videoHeight = -1;
private int previewWidth = -1, previewHeight = -1;
+
private boolean lastVideoSource = true;
-
private Conference mCachedConference = null;
- private ViewGroup rootView = null;
- private boolean ongoingCall = false;
- private EditText mNumeralDialEditText;
+ private boolean ongoingCall = false;
private DisplayManager.DisplayListener displayListener;
@@ -130,11 +162,11 @@
Log.i(TAG, "onAttach");
super.onAttach(activity);
- if (!(activity instanceof Callbacks)) {
+ if (!(activity instanceof ConversationCallbacks)) {
throw new IllegalStateException("Activity must implement fragment's callbacks.");
}
- mCallbacks = (Callbacks) activity;
+ mCallbacks = (ConversationCallbacks) activity;
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CallManagerCallBack.RECORD_STATE_CHANGED);
@@ -201,23 +233,21 @@
}
};
}
-
- setRetainInstance(true);
}
@Override
public void onDestroy() {
+ super.onDestroy();
Log.i(TAG, "onDestroy");
if (mScreenWakeLock != null && mScreenWakeLock.isHeld()) {
mScreenWakeLock.release();
}
- super.onDestroy();
}
/**
* The Activity calling this fragment has to implement this interface
*/
- public interface Callbacks extends LocalService.Callbacks {
+ public interface ConversationCallbacks extends LocalService.Callbacks {
void startTimer();
void terminateCall();
@@ -229,34 +259,46 @@
ActionBar getSupportActionBar();
}
- /**
- * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
- */
- private static class DummyCallbacks extends LocalService.DummyCallbacks implements Callbacks {
+ private static final ConversationCallbacks sDummyCallbacks = new ConversationCallbacks() {
+ @Override
+ public void startTimer() {
+ //Dummy implementation
+ }
+
@Override
public void terminateCall() {
+ //Dummy implementation
}
@Override
public Conference getDisplayedConference() {
+ //Dummy implementation
return null;
}
@Override
public void updateDisplayedConference(Conference c) {
+ //Dummy implementation
}
@Override
public ActionBar getSupportActionBar() {
+ //Dummy implementation
return null;
}
@Override
- public void startTimer() {
+ public IDRingService getRemoteService() {
+ //Dummy implementation
+ return null;
}
- }
- private static final Callbacks sDummyCallbacks = new DummyCallbacks();
+ @Override
+ public LocalService getService() {
+ //Dummy implementation
+ return null;
+ }
+ };
public class CallReceiver extends BroadcastReceiver {
private final String TAG = CallReceiver.class.getSimpleName();
@@ -267,25 +309,25 @@
if (action.contentEquals(LocalService.ACTION_CONF_UPDATE)) {
confUpdate();
} else if (action.contentEquals(DRingService.VIDEO_EVENT)) {
- if (video == null)
+ if (mVideoSurface == null)
return;
Conference conf = getConference();
if (intent.hasExtra("start")) {
- video.setVisibility(View.VISIBLE);
+ mVideoSurface.setVisibility(View.VISIBLE);
videoPreview.setVisibility(View.VISIBLE);
} else if (intent.hasExtra("camera")) {
previewWidth = intent.getIntExtra("width", 0);
previewHeight = intent.getIntExtra("height", 0);
} else if (conf != null && conf.getId().equals(intent.getStringExtra("call"))) {
- if (video != null) {
+ if (mVideoSurface != null) {
haveVideo = intent.getBooleanExtra("started", false);
if (haveVideo) {
- video.setVisibility(View.VISIBLE);
+ mVideoSurface.setVisibility(View.VISIBLE);
videoPreview.setVisibility(View.VISIBLE);
videoWidth = intent.getIntExtra("width", 0);
videoHeight = intent.getIntExtra("height", 0);
} else {
- video.setVisibility(View.GONE);
+ mVideoSurface.setVisibility(View.GONE);
videoPreview.setVisibility(View.GONE);
}
}
@@ -362,7 +404,7 @@
speakerPhoneBtn.setChecked(speakerPhone);
}
if (addContactBtn != null) {
- SipCall call = (getConference() != null && !getConference().getParticipants().isEmpty()) ? getConference().getParticipants().get(0) : null;
+ SipCall call = (getConference() != null && !getConference().getParticipants().isEmpty()) ? getFirstParticipant() : null;
addContactBtn.setVisible(call != null && null != call.getContact() && call.getContact().isUnknown());
}
@@ -384,12 +426,12 @@
Intent intent = new Intent()
.setClass(getActivity(), ConversationActivity.class)
.setAction(Intent.ACTION_VIEW)
- .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, getConference().getParticipants().get(0).getContact().getIds().get(0)));
+ .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, getFirstParticipant().getContact().getIds().get(0)));
intent.putExtra("resuming", true);
startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
break;
case R.id.menuitem_addcontact:
- startActivityForResult(getConference().getParticipants().get(0).getContact().getAddNumberIntent(), ConversationActivity.REQ_ADD_CONTACT);
+ startActivityForResult(getFirstParticipant().getContact().getAddNumberIntent(), ConversationActivity.REQ_ADD_CONTACT);
break;
case R.id.menuitem_speaker:
audioManager.setSpeakerphoneOn(!audioManager.isSpeakerphoneOn());
@@ -448,10 +490,10 @@
}
Conference c = getConference();
- if (c != null && video != null && c.resumeVideo) {
- Log.w(TAG, "Resuming video");
+ if (c != null && mVideoSurface != null && c.resumeVideo) {
+ Log.i(TAG, "Resuming video");
haveVideo = true;
- video.setVisibility(View.VISIBLE);
+ mVideoSurface.setVisibility(View.VISIBLE);
videoPreview.setVisibility(View.VISIBLE);
c.resumeVideo = false;
}
@@ -459,8 +501,8 @@
@Override
public void onResume() {
- Log.w(TAG, "onResume()");
super.onResume();
+ Log.i(TAG, "onResume()");
Conference c = getConference();
this.confUpdate();
@@ -476,7 +518,7 @@
if (c.resumeVideo) {
Log.w(TAG, "Resuming video");
haveVideo = true;
- video.setVisibility(View.VISIBLE);
+ mVideoSurface.setVisibility(View.VISIBLE);
videoPreview.setVisibility(View.VISIBLE);
c.resumeVideo = false;
}
@@ -576,7 +618,7 @@
@Override
public void rtcpReportReceived(Conference c, HashMap<String, Integer> stats) {
-
+ // No implementation yet
}
@Override
@@ -589,9 +631,7 @@
Conference c = data.getParcelableExtra("target");
transfer = data.getParcelableExtra("transfer");
try {
-
mCallbacks.getRemoteService().attendedTransfer(transfer.getCallId(), c.getParticipants().get(0).getCallId());
-
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -616,13 +656,17 @@
}
void resetVideoSizes() {
- double video_ratio = videoWidth / (double) videoHeight;
- double screen_ratio = rootView.getWidth() / (double) rootView.getHeight();
+ ViewGroup rootView = (ViewGroup) getView();
+ if (rootView == null)
+ return;
- FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) video.getLayoutParams();
+ double videoRatio = videoWidth / (double) videoHeight;
+ double screenRatio = getView().getWidth() / (double) getView().getHeight();
+
+ FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mVideoSurface.getLayoutParams();
int oldW = params.width;
int oldH = params.height;
- if (video_ratio >= screen_ratio) {
+ if (videoRatio >= screenRatio) {
params.width = RelativeLayout.LayoutParams.MATCH_PARENT;
params.height = (int) (videoHeight * (double) rootView.getWidth() / (double) videoWidth);
} else {
@@ -632,20 +676,20 @@
if (oldW != params.width || oldH != params.height) {
Log.w(TAG, "onLayoutChange " + params.width + " x " + params.height);
- video.setLayoutParams(params);
+ mVideoSurface.setLayoutParams(params);
}
DisplayMetrics metrics = getResources().getDisplayMetrics();
- FrameLayout.LayoutParams params_preview = (FrameLayout.LayoutParams) videoPreview.getLayoutParams();
- oldW = params_preview.width;
- oldH = params_preview.height;
- double preview_max_dim = Math.max(previewWidth, previewHeight);
- double preview_ratio = metrics.density * 160. / preview_max_dim;
- params_preview.width = (int) (previewWidth * preview_ratio);
- params_preview.height = (int) (previewHeight * preview_ratio);
- if (oldW != params_preview.width || oldH != params_preview.height) {
- Log.w(TAG, "onLayoutChange " + params_preview.width + " x " + params_preview.height);
- videoPreview.setLayoutParams(params_preview);
+ FrameLayout.LayoutParams paramsPreview = (FrameLayout.LayoutParams) videoPreview.getLayoutParams();
+ oldW = paramsPreview.width;
+ oldH = paramsPreview.height;
+ double previewMaxDim = Math.max(previewWidth, previewHeight);
+ double previewRatio = metrics.density * 160. / previewMaxDim;
+ paramsPreview.width = (int) (previewWidth * previewRatio);
+ paramsPreview.height = (int) (previewHeight * previewRatio);
+ if (oldW != paramsPreview.width || oldH != paramsPreview.height) {
+ Log.i(TAG, "onLayoutChange " + paramsPreview.width + " x " + paramsPreview.height);
+ videoPreview.setLayoutParams(paramsPreview);
}
}
@@ -664,9 +708,10 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
- rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
+ View rootView = inflater.inflate(R.layout.frag_call, container, false);
- mNumeralDialEditText = (EditText) rootView.findViewById(R.id.dialpad_edit_text);
+ ButterKnife.bind(this, rootView);
+
mNumeralDialEditText.requestFocus();
mNumeralDialEditText.addTextChangedListener(new TextWatcher() {
@Override
@@ -694,20 +739,9 @@
}
});
- contactBubbleLayout = rootView.findViewById(R.id.contact_bubble_layout);
- contactBubbleView = (ImageView) rootView.findViewById(R.id.contact_bubble);
- contactBubbleTxt = (TextView) rootView.findViewById(R.id.contact_bubble_txt);
- contactBubbleNumTxt = (TextView) rootView.findViewById(R.id.contact_bubble_num_txt);
- acceptButton = rootView.findViewById(R.id.call_accept_btn);
- refuseButton = rootView.findViewById(R.id.call_refuse_btn);
- hangupButton = rootView.findViewById(R.id.call_hangup_btn);
- mCallStatusTxt = (TextView) rootView.findViewById(R.id.call_status_txt);
- mSecuritySwitch = (ViewSwitcher) rootView.findViewById(R.id.security_switcher);
- securityIndicator = rootView.findViewById(R.id.security_indicator);
- video = (SurfaceView) rootView.findViewById(R.id.video_preview_surface);
- video.getHolder().setFormat(PixelFormat.RGBA_8888);
- video.getHolder().addCallback(new SurfaceHolder.Callback() {
+ mVideoSurface.getHolder().setFormat(PixelFormat.RGBA_8888);
+ mVideoSurface.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
contactBubbleLayout.setVisibility(View.GONE);
@@ -755,7 +789,6 @@
}
});
- videoPreview = (SurfaceView) rootView.findViewById(R.id.camera_preview_surface);
videoPreview.getHolder().setFormat(PixelFormat.RGBA_8888);
videoPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
@@ -803,6 +836,7 @@
}
private void initContactDisplay(final SipCall call) {
+
CallContact contact = call.getContact();
final String name = contact.getDisplayName();
contactBubbleTxt.setText(name);
@@ -812,7 +846,11 @@
contactBubbleNumTxt.setVisibility(View.VISIBLE);
contactBubbleNumTxt.setText(call.getNumber());
}
+
+ mPulseAnimation.startRippleAnimation();
+
new ContactPictureTask(getActivity(), contactBubbleView, contact).run();
+
ActionBar ab = mCallbacks.getSupportActionBar();
ab.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE);
ab.setTitle(name);
@@ -823,30 +861,16 @@
mCallbacks.startTimer();
acceptButton.setVisibility(View.GONE);
refuseButton.setVisibility(View.GONE);
+ hangupButton.setVisibility(View.VISIBLE);
- final SipCall call = getConference().getParticipants().get(0);
- final String call_id = call.getCallId();
+ final SipCall call = getFirstParticipant();
initContactDisplay(call);
if (getActivity() != null) {
getActivity().invalidateOptionsMenu();
}
- hangupButton.setVisibility(View.VISIBLE);
- hangupButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- mCallbacks.getRemoteService().hangUp(call_id);
- mCallbacks.terminateCall();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- });
-
contactBubbleLayout.setVisibility(haveVideo ? View.GONE : View.VISIBLE);
-
updateSecurityDisplay();
}
@@ -864,7 +888,7 @@
if (getConference().hasMultipleParticipants()) {
//TODO What layout should we put?
} else {
- final SecureSipCall secured = (SecureSipCall) getConference().getParticipants().get(0);
+ final SecureSipCall secured = (SecureSipCall) getFirstParticipant();
switch (secured.displayModule()) {
case SecureSipCall.DISPLAY_GREEN_LOCK:
Log.i(TAG, "DISPLAY_GREEN_LOCK");
@@ -903,17 +927,9 @@
mSecuritySwitch.setVisibility(View.VISIBLE);
}
- /*protected Bitmap getContactPhoto(CallContact contact, int size) {
- if (contact.getPhotoId() > 0) {
- return ContactPictureTask.loadContactPhoto(getActivity().getContentResolver(), contact.getId());
- } else {
- return ContactPictureTask.decodeSampledBitmapFromResource(getResources(), R.drawable.ic_contact_picture, size, size);
- }
- }*/
-
private void initIncomingCallDisplay() {
Log.i(TAG, "Start incoming display");
- final SipCall call = getConference().getParticipants().get(0);
+ final SipCall call = getFirstParticipant();
if (mCallbacks.getService().getAccount(call.getAccount()).isAutoanswerEnabled()) {
try {
mCallbacks.getRemoteService().accept(call.getCallId());
@@ -923,32 +939,7 @@
} else {
initContactDisplay(call);
acceptButton.setVisibility(View.VISIBLE);
- acceptButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- acceptButton.setOnClickListener(null);
- refuseButton.setOnClickListener(null);
- try {
- mCallbacks.getRemoteService().accept(call.getCallId());
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- });
refuseButton.setVisibility(View.VISIBLE);
- refuseButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- acceptButton.setOnClickListener(null);
- refuseButton.setOnClickListener(null);
- try {
- mCallbacks.getRemoteService().refuse(call.getCallId());
- mCallbacks.terminateCall();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- });
hangupButton.setVisibility(View.GONE);
}
}
@@ -956,51 +947,60 @@
private void initOutGoingCallDisplay() {
Log.i(TAG, "Start outgoing display");
- final SipCall call = getConference().getParticipants().get(0);
+ final SipCall call = getFirstParticipant();
initContactDisplay(call);
acceptButton.setVisibility(View.GONE);
- refuseButton.setVisibility(View.GONE);
-
- hangupButton.setVisibility(View.VISIBLE);
- hangupButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- mCallbacks.getRemoteService().hangUp(call.getCallId());
- mCallbacks.terminateCall();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- }
- });
-
+ refuseButton.setVisibility(View.VISIBLE);
+ hangupButton.setVisibility(View.GONE);
}
- /*
- public void makeTransfer(BubbleContact contact) {
- FragmentManager fm = getFragmentManager();
- editName = TransferDFragment.newInstance();
- Bundle b = new Bundle();
- try {
- b.putParcelableArrayList("calls", (ArrayList<Conference>) mCallbacks.getRemoteService().getConcurrentCalls());
- b.putParcelable("call_selected", contact.associated_call);
- editName.setArguments(b);
- editName.setTargetFragment(this, REQUEST_TRANSFER);
- editName.show(fm, "");
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
- }
-
- }*/
-
public void updateTime() {
if (getConference() != null && !getConference().getParticipants().isEmpty()) {
- long duration = System.currentTimeMillis() - getConference().getParticipants().get(0).getTimestampStart();
+ long duration = System.currentTimeMillis() - getFirstParticipant().getTimestampStart();
duration = duration / 1000;
if (getConference().isOnGoing())
mCallStatusTxt.setText(String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
}
+ }
+ @OnClick({R.id.call_hangup_btn, R.id.call_refuse_btn})
+ public void hangUpClicked() {
+ try {
+ final SipCall call = getFirstParticipant();
+ if (call == null) {
+ return;
+ }
+ final String callId = call.getCallId();
+ mCallbacks.getRemoteService().hangUp(callId);
+ mCallbacks.terminateCall();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @OnClick(R.id.call_accept_btn)
+ public void acceptClicked() {
+ final SipCall call = getFirstParticipant();
+ if (call == null) {
+ return;
+ }
+ try {
+ mCallbacks.getRemoteService().accept(call.getCallId());
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Helper accessor that check nullity or emptiness of components to access first call participant
+ * @return the first participant or null
+ */
+ @Nullable
+ private SipCall getFirstParticipant() {
+ if (getConference() == null || getConference().getParticipants() == null || getConference().getParticipants().isEmpty()) {
+ return null;
+ }
+ return getConference().getParticipants().get(0);
}
}
diff --git a/ring-android/app/src/main/res/layout-land/frag_call.xml b/ring-android/app/src/main/res/layout-land/frag_call.xml
new file mode 100644
index 0000000..8fa4aa6
--- /dev/null
+++ b/ring-android/app/src/main/res/layout-land/frag_call.xml
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+Copyright (C) 2004-2016 Savoir-faire Linux Inc.
+
+Author: Adrien Beraud <adrien.beraud@savoirfairelinux.com>
+
+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 <http://www.gnu.org/licenses/>.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".client.CallActivity">
+
+ <SurfaceView
+ android:id="@+id/video_preview_surface"
+ android:layout_width="match_parent"
+ android:layout_height="32dp"
+ android:layout_gravity="center"
+ android:visibility="gone" />
+
+ <FrameLayout
+ android:id="@+id/inner_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fitsSystemWindows="true">
+
+ <SurfaceView
+ android:id="@+id/camera_preview_surface"
+ android:layout_width="160dp"
+ android:layout_height="120dp"
+ android:layout_gravity="bottom|end"
+ android:layout_margin="8dp"
+ android:visibility="gone" />
+
+ <LinearLayout
+ android:id="@+id/contact_bubble_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:weightSum="100"
+ android:orientation="horizontal"
+ android:layout_marginBottom="16dp">
+
+ <com.skyfishjy.library.RippleBackground
+ android:id="@+id/ripple_animation"
+ android:layout_width="0dp"
+ android:layout_weight="50"
+ android:layout_height="match_parent"
+ app:rb_color="@color/white"
+ app:rb_duration="5000"
+ app:rb_radius="20dp"
+ app:rb_rippleAmount="3"
+ app:rb_scale="6">
+
+ <ImageView
+ android:id="@+id/contact_bubble"
+ android:layout_width="160dp"
+ android:layout_height="160dp"
+ android:layout_centerInParent="true"
+ tools:src="@drawable/ic_contact_picture" />
+ </com.skyfishjy.library.RippleBackground>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:layout_weight="50"
+ android:layout_margin="10dp"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/contact_bubble_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="@color/text_color_primary_dark"
+ tools:text="Contact Name" />
+
+ <TextView
+ android:id="@+id/contact_bubble_num_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:ellipsize="end"
+ android:paddingEnd="32dp"
+ android:paddingStart="32dp"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/text_color_secondary_dark"
+ tools:text="ring:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
+
+ <TextView
+ android:id="@+id/call_status_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:textColor="@color/text_color_primary_dark"
+ android:textSize="16sp"
+ tools:text="Connecting" />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="12dp"
+ android:orientation="horizontal">
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/call_refuse_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dp"
+ android:contentDescription="@string/action_call_decline"
+ android:src="@drawable/ic_call_end_white_24dp"
+ app:backgroundTint="@color/error_red"
+ app:elevation="6dp"
+ app:pressedTranslationZ="12dp"
+ app:rippleColor="@android:color/white" />
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/call_accept_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dp"
+ android:contentDescription="@string/action_call_accept"
+ android:src="@drawable/ic_call_white_24dp"
+ app:backgroundTint="#4caf50"
+ app:elevation="6dp"
+ app:pressedTranslationZ="12dp"
+ app:rippleColor="@android:color/white" />
+ </LinearLayout>
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/imageView"
+ android:layout_gravity="center_horizontal" />
+
+
+ </LinearLayout>
+ </LinearLayout>
+
+ <RelativeLayout
+ android:id="@+id/call_status_bar"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:visibility="visible">
+
+ <ViewSwitcher
+ android:id="@+id/security_switcher"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:visibility="gone">
+
+ <Button
+ android:id="@+id/confirm_sas"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:textColor="@android:color/white"
+ android:textSize="12sp" />
+
+ <ImageView
+ android:id="@+id/lock_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|center_vertical" />
+ </ViewSwitcher>
+
+ <ImageView
+ android:id="@+id/security_indicator"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ android:layout_margin="16dp"
+ android:src="@drawable/ic_lock_white_24dp"
+ android:tint="#4caf50"
+ android:visibility="gone" />
+
+ </RelativeLayout>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/call_hangup_btn"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom|center_horizontal"
+ android:layout_margin="28dp"
+ android:src="@drawable/ic_call_end_white_24dp"
+ app:backgroundTint="@color/error_red"
+ app:elevation="6dp"
+ app:pressedTranslationZ="12dp"
+ app:rippleColor="@android:color/white" />
+
+ <EditText
+ android:id="@+id/dialpad_edit_text"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:ems="10"
+ android:inputType="phone"
+ android:visibility="visible" />
+
+ </FrameLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/activity_call_layout.xml b/ring-android/app/src/main/res/layout/activity_call_layout.xml
index f12e443..cf29ef5 100644
--- a/ring-android/app/src/main/res/layout/activity_call_layout.xml
+++ b/ring-android/app/src/main/res/layout/activity_call_layout.xml
@@ -20,7 +20,7 @@
<cx.ring.views.FitsWindowsLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/maincalllayout"
+ android:id="@+id/main_call_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/cardview_dark_background"
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index 656d3c7..7c9f8c9 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -44,53 +44,76 @@
android:layout_margin="8dp"
android:visibility="gone" />
- <LinearLayout
+ <RelativeLayout
android:id="@+id/contact_bubble_layout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_marginBottom="16dp"
- android:gravity="center_horizontal"
- android:orientation="vertical">
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center"
+ android:layout_marginBottom="16dp">
- <ImageView
- android:id="@+id/contact_bubble"
- android:layout_width="160dp"
- android:layout_height="160dp"
- android:layout_marginBottom="16dp"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp" />
+ <com.skyfishjy.library.RippleBackground
+ android:id="@+id/ripple_animation"
+ android:layout_width="230dp"
+ android:layout_height="230dp"
+ android:layout_centerInParent="true"
+ app:rb_color="@color/white"
+ app:rb_duration="5000"
+ app:rb_radius="20dp"
+ app:rb_rippleAmount="3"
+ app:rb_scale="6">
- <TextView
- android:id="@+id/contact_bubble_txt"
- android:layout_width="match_parent"
+ <ImageView
+ android:id="@+id/contact_bubble"
+ android:layout_width="160dp"
+ android:layout_height="160dp"
+ android:layout_centerInParent="true"
+ tools:src="@drawable/ic_contact_picture" />
+ </com.skyfishjy.library.RippleBackground>
+
+ <LinearLayout
+ android:layout_width="300dp"
android:layout_height="wrap_content"
- android:gravity="center_horizontal"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@color/text_color_primary_dark" />
+ android:layout_below="@id/ripple_animation"
+ android:layout_centerHorizontal="true"
+ android:layout_margin="10dp"
+ android:orientation="vertical">
- <TextView
- android:id="@+id/contact_bubble_num_txt"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="middle"
- android:gravity="center_horizontal"
- android:paddingEnd="8dp"
- android:paddingStart="8dp"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/text_color_secondary_dark" />
+ <TextView
+ android:id="@+id/contact_bubble_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textColor="@color/text_color_primary_dark"
+ tools:text="Contact Name" />
- <TextView
- android:id="@+id/call_status_txt"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/text_color_primary_dark"
- android:textSize="16sp" />
+ <TextView
+ android:id="@+id/contact_bubble_num_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:ellipsize="end"
+ android:paddingEnd="32dp"
+ android:paddingStart="32dp"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="@color/text_color_secondary_dark"
+ tools:text="ring:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
- </LinearLayout>
+ <TextView
+ android:id="@+id/call_status_txt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:textColor="@color/text_color_primary_dark"
+ android:textSize="16sp"
+ tools:text="Connecting" />
+
+ </LinearLayout>
+
+
+ </RelativeLayout>
<LinearLayout
android:layout_width="wrap_content"