diff --git a/res/drawable/sel_call.png b/res/drawable/sel_call.png new file mode 100644 index 000000000..f4fd83b8f Binary files /dev/null and b/res/drawable/sel_call.png differ diff --git a/res/drawable/sel_call_first.png b/res/drawable/sel_call_first.png new file mode 100644 index 000000000..17b55ffef Binary files /dev/null and b/res/drawable/sel_call_first.png differ diff --git a/res/layout/active_call.xml b/res/layout/active_call.xml new file mode 100644 index 000000000..51e83b8f6 --- /dev/null +++ b/res/layout/active_call.xml @@ -0,0 +1,28 @@ + + + + + + + + \ No newline at end of file diff --git a/res/layout/audio.xml b/res/layout/audio.xml index c4c65f0e1..1c96d3823 100644 --- a/res/layout/audio.xml +++ b/res/layout/audio.xml @@ -1,46 +1,23 @@ - + - + android:orientation="vertical"> - - - - - - - + @@ -58,4 +35,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/res/layout/chat.xml b/res/layout/chat.xml index f66feb2ee..ca126b373 100644 --- a/res/layout/chat.xml +++ b/res/layout/chat.xml @@ -18,8 +18,8 @@ false false false - true + false false true true diff --git a/src/org/linphone/AudioCallFragment.java b/src/org/linphone/AudioCallFragment.java index b45e8c983..65486dbc0 100644 --- a/src/org/linphone/AudioCallFragment.java +++ b/src/org/linphone/AudioCallFragment.java @@ -22,13 +22,13 @@ import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCoreFactory; import android.app.Activity; -import android.net.Uri; +import android.content.res.Resources; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; /** @@ -36,47 +36,86 @@ import android.widget.TextView; */ public class AudioCallFragment extends Fragment { private static AudioCallFragment instance; -// private Chronometer timer; + private LinearLayout callsList; + private LayoutInflater inflater; + private ViewGroup container; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { instance = this; + this.inflater = inflater; + this.container = container; + View view = inflater.inflate(R.layout.audio, container, false); -// timer = (Chronometer) view.findViewById(R.id.callTimer); + callsList = (LinearLayout) view.findViewById(R.id.calls); - LinphoneCall currentCall; - do { - currentCall = LinphoneManager.getLc().getCurrentCall(); - } while (currentCall == null); - - String sipUri = currentCall.getRemoteAddress().asStringUriOnly(); - LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); - Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, view.getContext().getContentResolver()); - - TextView contact = (TextView) view.findViewById(R.id.contactNameOrNumber); - contact.setText(lAddress.getDisplayName() == null ? sipUri : lAddress.getDisplayName()); - - ImageView contactPicture = (ImageView) view.findViewById(R.id.contactPicture); - if (pictureUri != null) { - LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture, Uri.parse(pictureUri.toString()), R.drawable.unknown_small); - } - return view; } + + private void displayCall(Resources resources, LinearLayout callView, LinphoneCall call) { + String sipUri = call.getRemoteAddress().asStringUriOnly(); + LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri); +// Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, callView.getContext().getContentResolver()); + + TextView contact = (TextView) callView.findViewById(R.id.contactNameOrNumber); + if (lAddress.getDisplayName() == null) { + if (resources.getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) { + contact.setText(LinphoneUtils.getUsernameFromAddress(sipUri)); + } else { + contact.setText(sipUri); + } + } else { + contact.setText(lAddress.getDisplayName()); + } + +// ImageView contactPicture = (ImageView) callView.findViewById(R.id.contactPicture); +// if (pictureUri != null) { +// LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture, Uri.parse(pictureUri.toString()), R.drawable.unknown_small); +// } + } @Override public void onAttach(Activity activity) { super.onAttach(activity); + InCallActivity.instance().bindAudioFragment(this); // Just to be sure we have incall controls InCallActivity.instance().setCallControlsVisibleAndRemoveCallbacks(); } + @Override + public void onResume() { + super.onResume(); + + // Add calls + refreshCallList(getResources()); + } + /** * @return null if not ready yet */ public static AudioCallFragment instance() { return instance; } + + public void refreshCallList(Resources resources) { + callsList.removeAllViews(); + + boolean first = true; + for (LinphoneCall call : LinphoneManager.getLc().getCalls()) { + LinearLayout callView = (LinearLayout) inflater.inflate(R.layout.active_call, container, false); + displayCall(resources, callView, call); + + if (first) { + callView.setBackgroundResource(R.drawable.sel_call_first); + first = false; + } else { + callView.setBackgroundResource(R.drawable.sel_call); + } + + callsList.addView(callView); + } + callsList.invalidate(); + } } diff --git a/src/org/linphone/ContactFragment.java b/src/org/linphone/ContactFragment.java index 14df5fe6e..90af9eccc 100644 --- a/src/org/linphone/ContactFragment.java +++ b/src/org/linphone/ContactFragment.java @@ -85,7 +85,7 @@ public class ContactFragment extends Fragment { return new OnClickListener() { @Override public void onClick(View v) { - LinphoneActivity.instance().setAddressAndGoToDialer(v.getTag().toString(), contact.getName(), contact.getPhotoUri()); + LinphoneActivity.instance().setAddresGoToDialerAndCall(v.getTag().toString(), contact.getName(), contact.getPhotoUri()); } }; } diff --git a/src/org/linphone/DialerFragment.java b/src/org/linphone/DialerFragment.java index 452c35bc1..89c6abcc1 100644 --- a/src/org/linphone/DialerFragment.java +++ b/src/org/linphone/DialerFragment.java @@ -119,6 +119,7 @@ public class DialerFragment extends Fragment { public void resetLayout() { if (LinphoneActivity.instance().isInCallLayout()) { mCall.setImageResource(R.drawable.plus); + mAddress.setText(""); mAddContact.setImageResource(R.drawable.cancel); mAddContact.setOnClickListener(cancelListener); } else { diff --git a/src/org/linphone/HistoryDetailFragment.java b/src/org/linphone/HistoryDetailFragment.java index 20e9d3e60..87b221a14 100644 --- a/src/org/linphone/HistoryDetailFragment.java +++ b/src/org/linphone/HistoryDetailFragment.java @@ -98,7 +98,7 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener { int id = v.getId(); if (id == R.id.dialBack) { - LinphoneActivity.instance().setAddressAndGoToDialer(sipUri, displayName, pictureUri == null ? null : Uri.parse(pictureUri)); + LinphoneActivity.instance().setAddresGoToDialerAndCall(sipUri, displayName, pictureUri == null ? null : Uri.parse(pictureUri)); } else if (id == R.id.chat) { LinphoneActivity.instance().displayChat(sipUri); } else if (id == R.id.addToContacts) { diff --git a/src/org/linphone/InCallActivity.java b/src/org/linphone/InCallActivity.java index 95adf7068..69e82f461 100644 --- a/src/org/linphone/InCallActivity.java +++ b/src/org/linphone/InCallActivity.java @@ -83,6 +83,15 @@ public class InCallActivity extends FragmentActivity implements } initUI(); + if (LinphoneManager.getLc().getCallsNb() > 0) { + LinphoneCall call = LinphoneManager.getLc().getCalls()[0]; + + if (isCallEstablished(call)) { + enableAndRefreshInCallActions(); + isVideoEnabled = call.getCurrentParamsCopy().getVideoEnabled(); + } + } + Fragment callFragment; if (isVideoEnabled) { callFragment = new VideoCallFragment(); @@ -400,12 +409,22 @@ public class InCallActivity extends FragmentActivity implements state == LinphoneCall.State.StreamsRunning || state == LinphoneCall.State.Resuming; } + + private boolean isCallEstablished(LinphoneCall call) { + LinphoneCall.State state = call.getState(); + + return isCallRunning(call) || + state == LinphoneCall.State.Paused || + state == LinphoneCall.State.PausedByRemote || + state == LinphoneCall.State.Pausing; + } @Override public void onCallStateChanged(LinphoneCall call, State state, String message) { if (LinphoneManager.getLc().getCallsNb() == 0) { finish(); + return; } if (state == State.StreamsRunning) { @@ -418,6 +437,17 @@ public class InCallActivity extends FragmentActivity implements isMicMuted = LinphoneManager.getLc().isMicMuted(); enableAndRefreshInCallActions(); } + + if (state == State.CallEnd || state == State.CallReleased || state == State.Error) { + if (audioCallFragment != null) { + mHandler.post(new Runnable() { + @Override + public void run() { + audioCallFragment.refreshCallList(getResources()); + } + }); + } + } } @Override @@ -452,4 +482,8 @@ public class InCallActivity extends FragmentActivity implements if (LinphoneUtils.onKeyBackGoHome(this, keyCode, event)) return true; return super.onKeyDown(keyCode, event); } + + public void bindAudioFragment(AudioCallFragment fragment) { + audioCallFragment = fragment; + } } diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java index 1811d6dae..423480d2d 100644 --- a/src/org/linphone/LinphoneActivity.java +++ b/src/org/linphone/LinphoneActivity.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.List; +import org.linphone.LinphoneManager.AddressType; import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener; import org.linphone.LinphoneSimpleListener.LinphoneOnMessageReceived; import org.linphone.LinphoneSimpleListener.LinphoneOnRegistrationStateChangedListener; @@ -38,6 +39,7 @@ import org.linphone.core.LinphoneCore.RegistrationState; import org.linphone.core.LinphoneCoreFactory; import org.linphone.core.Log; import org.linphone.setup.SetupActivity; +import org.linphone.ui.AddressText; import android.app.Activity; import android.content.Intent; @@ -466,12 +468,17 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene } @Override - public void setAddressAndGoToDialer(String number, String name, Uri photo) { + public void setAddresGoToDialerAndCall(String number, String name, Uri photo) { Bundle extras = new Bundle(); extras.putString("SipUri", number); extras.putString("DisplayName", name); extras.putString("Photo", photo == null ? null : photo.toString()); changeCurrentFragment(FragmentsAvailable.DIALER, extras); + + AddressType address = new AddressText(this, null); + address.setDisplayedName(name); + address.setText(number); + LinphoneManager.getInstance().newOutgoingCall(address); } public void setAddressAndGoToDialer(String number) { @@ -603,6 +610,6 @@ public class LinphoneActivity extends FragmentActivity implements OnClickListene } interface ContactPicked { - void setAddressAndGoToDialer(String number, String name, Uri photo); + void setAddresGoToDialerAndCall(String number, String name, Uri photo); void goToDialer(); } \ No newline at end of file diff --git a/src/org/linphone/StatusFragment.java b/src/org/linphone/StatusFragment.java index f7da537a6..2df066da7 100644 --- a/src/org/linphone/StatusFragment.java +++ b/src/org/linphone/StatusFragment.java @@ -181,8 +181,8 @@ public class StatusFragment extends Fragment { } public void refreshEncryptionIcon() { - if (encryption != null) { - LinphoneCall call = LinphoneManager.getLc().getCurrentCall(); + LinphoneCall call = LinphoneManager.getLc().getCurrentCall(); + if (call != null && encryption != null) { MediaEncryption mediaEncryption = call.getCurrentParamsCopy().getMediaEncryption(); encryption.setVisibility(View.VISIBLE); diff --git a/src/org/linphone/VideoCallFragment.java b/src/org/linphone/VideoCallFragment.java index cbbd71814..816eda5a3 100644 --- a/src/org/linphone/VideoCallFragment.java +++ b/src/org/linphone/VideoCallFragment.java @@ -22,6 +22,7 @@ import org.linphone.core.Log; import org.linphone.mediastream.video.AndroidVideoWindowImpl; import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; +import android.annotation.TargetApi; import android.content.Context; import android.opengl.GLSurfaceView; import android.os.Bundle; @@ -39,6 +40,7 @@ import android.view.ViewGroup; /** * @author Sylvain Berfini */ +@TargetApi(5) public class VideoCallFragment extends Fragment { private static VideoCallFragment instance; private WakeLock mWakeLock; @@ -113,15 +115,19 @@ public class VideoCallFragment extends Fragment { } public void switchCamera() { - int videoDeviceId = LinphoneManager.getLc().getVideoDevice(); - videoDeviceId = (videoDeviceId + 1) % AndroidCameraConfiguration.retrieveCameras().length; - LinphoneManager.getLc().setVideoDevice(videoDeviceId); - CallManager.getInstance().updateCall(); - - // previous call will cause graph reconstruction -> regive preview - // window - if (mCaptureView != null) { - LinphoneManager.getLc().setPreviewWindow(mCaptureView); + try { + int videoDeviceId = LinphoneManager.getLc().getVideoDevice(); + videoDeviceId = (videoDeviceId + 1) % AndroidCameraConfiguration.retrieveCameras().length; + LinphoneManager.getLc().setVideoDevice(videoDeviceId); + CallManager.getInstance().updateCall(); + + // previous call will cause graph reconstruction -> regive preview + // window + if (mCaptureView != null) { + LinphoneManager.getLc().setPreviewWindow(mCaptureView); + } + } catch (ArithmeticException ae) { + Log.e("Cannot swtich camera : no camera"); } } diff --git a/src/org/linphone/ui/CallButton.java b/src/org/linphone/ui/CallButton.java index 5da1bb8bb..9acbb74eb 100644 --- a/src/org/linphone/ui/CallButton.java +++ b/src/org/linphone/ui/CallButton.java @@ -48,7 +48,7 @@ public class CallButton extends ImageView implements OnClickListener, AddressAwa public void onClick(View v) { try { if (!LinphoneManager.getInstance().acceptCallIfIncomingPending()) { - if (mAddress.getText().length() >0) { + if (mAddress.getText().length() > 0) { LinphoneManager.getInstance().newOutgoingCall(mAddress); } }