Added audio call stats
This commit is contained in:
parent
5e675d06d8
commit
f400b4c562
7 changed files with 291 additions and 12 deletions
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/cancel_white_bg_over" />
|
||||
android:drawable="@drawable/back_over" />
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/cancel_white_bg_disabled" />
|
||||
android:drawable="@drawable/back_disabled" />
|
||||
<item
|
||||
android:drawable="@drawable/cancel_white_bg_default" />
|
||||
android:drawable="@drawable/back_default" />
|
||||
</selector>
|
|
@ -45,12 +45,140 @@
|
|||
|
||||
</LinearLayout>
|
||||
|
||||
<org.linphone.ui.AvatarWithShadow
|
||||
android:id="@+id/contactPicture"
|
||||
android:layout_width="wrap_content"
|
||||
<ViewFlipper
|
||||
android:id="@+id/flipper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
linphone:picture="@drawable/unknown_small"
|
||||
android:layout_gravity="center"
|
||||
android:paddingBottom="10dp" />
|
||||
android:paddingBottom="10dp">
|
||||
|
||||
<org.linphone.ui.AvatarWithShadow
|
||||
android:id="@+id/contactPicture"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
linphone:picture="@drawable/unknown_small" />
|
||||
|
||||
<TableLayout
|
||||
android:id="@+id/audioCallStats"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:padding="5dp">
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/call_stats_audio"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_default"
|
||||
android:textSize="18dp"/>
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/call_stats_codec"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/audioCodec"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:gravity="right|center_vertical"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/call_stats_upload"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/audioUploadBandwith"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:gravity="right|center_vertical"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/call_stats_download"
|
||||
android:textColor="@android:color/black"
|
||||
android:textStyle="bold"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/audioDownloadBandwith"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:gravity="right|center_vertical"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/call_stats_ice"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/ice"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="5dp"
|
||||
android:gravity="right|center_vertical"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14dp"/>
|
||||
|
||||
</TableRow>
|
||||
|
||||
</TableLayout>
|
||||
|
||||
</ViewFlipper>
|
||||
|
||||
</LinearLayout>
|
|
@ -210,6 +210,12 @@
|
|||
<string name="no_sip_contact">Aucun contact SIP dans votre carnet d\'adresse.</string>
|
||||
<string name="no_chat_history">Aucun historique de chat.</string>
|
||||
|
||||
<string name="call_stats_audio">Audio</string>
|
||||
<string name="call_stats_codec">Codec :</string>
|
||||
<string name="call_stats_upload">Bande passante envoi :</string>
|
||||
<string name="call_stats_download">Bande passante reception :</string>
|
||||
<string name="call_stats_ice">Connexion ICE :</string>
|
||||
|
||||
<!-- Used by Android to help blind people by describing them images -->
|
||||
<string name="content_description_add_contact"></string>
|
||||
<string name="content_description_about"></string>
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
<bool name="display_messages_time_and_status">true</bool> <!-- Used to show the time of each message arrival -->
|
||||
<bool name="display_time_aside">false</bool> <!-- if display_messages_time = true, display time on the side of the message instead of below -->
|
||||
|
||||
<bool name="display_call_stats">true</bool>
|
||||
|
||||
<!-- Behavior Settings -->
|
||||
<bool name="call_last_log_if_adress_is_empty">true</bool>
|
||||
<bool name="allow_ringing_while_early_media">true</bool>
|
||||
<bool name="allow_transfers">true</bool>
|
||||
|
|
|
@ -260,6 +260,12 @@
|
|||
<string name="no_sip_contact">No SIP contact in your address book.</string>
|
||||
<string name="no_chat_history">No chat history.</string>
|
||||
|
||||
<string name="call_stats_audio">Audio</string>
|
||||
<string name="call_stats_codec">Codec:</string>
|
||||
<string name="call_stats_upload">Upload bandwidth:</string>
|
||||
<string name="call_stats_download">Download bandwidth:</string>
|
||||
<string name="call_stats_ice">ICE connectivity:</string>
|
||||
|
||||
<!-- Used by Android to help blind people by describing them images -->
|
||||
<string name="content_description_add_contact">Add to contacts button</string>
|
||||
<string name="content_description_about"></string>
|
||||
|
|
|
@ -17,9 +17,13 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import org.linphone.core.LinphoneAddress;
|
||||
import org.linphone.core.LinphoneCall;
|
||||
import org.linphone.core.LinphoneCall.State;
|
||||
import org.linphone.core.LinphoneCallStats;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.ui.AvatarWithShadow;
|
||||
|
||||
|
@ -27,17 +31,21 @@ import android.app.Activity;
|
|||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Chronometer;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewFlipper;
|
||||
|
||||
/**
|
||||
* @author Sylvain Berfini
|
||||
|
@ -51,6 +59,10 @@ public class AudioCallFragment extends Fragment implements OnClickListener {
|
|||
private static final int conferenceMargin = 20;
|
||||
private static final int topMarginWithImage = topMargin + rowImageHeight + botMarginIfImage;
|
||||
|
||||
private static final int FLIPPER_AVATAR_VIEW = 0;
|
||||
private static final int FLIPPER_AUDIO_STATS_VIEW = 1;
|
||||
|
||||
private Handler mHandler = new Handler();
|
||||
private RelativeLayout callsList;
|
||||
private LayoutInflater inflater;
|
||||
private ViewGroup container;
|
||||
|
@ -93,7 +105,7 @@ public class AudioCallFragment extends Fragment implements OnClickListener {
|
|||
|
||||
setContactName(callView, lAddress, sipUri, resources);
|
||||
boolean hide = displayCallStatusIconAndReturnCallPaused(callView, call);
|
||||
displayOrHideContactPicture(callView, pictureUri, hide);
|
||||
displayOrHideContactPictureAndStats(callView, pictureUri, call, hide);
|
||||
setRowBackgroundAndPadding(callView, resources, index, call, !hide);
|
||||
registerCallDurationTimer(callView, call);
|
||||
previousCallIsActive = !hide;
|
||||
|
@ -142,14 +154,94 @@ public class AudioCallFragment extends Fragment implements OnClickListener {
|
|||
return isCallPaused || isInConference;
|
||||
}
|
||||
|
||||
private void displayOrHideContactPicture(LinearLayout callView, Uri pictureUri, boolean hide) {
|
||||
private void displayOrHideContactPictureAndStats(LinearLayout callView, Uri pictureUri, LinphoneCall call, boolean hide) {
|
||||
ViewFlipper flipper = (ViewFlipper) callView.findViewById(R.id.flipper);
|
||||
flipper.setDisplayedChild(FLIPPER_AVATAR_VIEW);
|
||||
|
||||
AvatarWithShadow contactPicture = (AvatarWithShadow) callView.findViewById(R.id.contactPicture);
|
||||
if (pictureUri != null) {
|
||||
LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture.getView(), Uri.parse(pictureUri.toString()), R.drawable.unknown_small);
|
||||
}
|
||||
if (hide) {
|
||||
contactPicture.setVisibility(View.GONE);
|
||||
flipper.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (getActivity().getResources().getBoolean(R.bool.display_call_stats)) {
|
||||
View audioCallstats = callView.findViewById(R.id.audioCallStats);
|
||||
if (call != null) {
|
||||
flipper.setEnabled(true);
|
||||
initAudioStatsRefresher(call, audioCallstats);
|
||||
initFlipperListeners(flipper);
|
||||
}
|
||||
} else {
|
||||
flipper.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAudioStatsRefresher(final LinphoneCall call, final View view) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Timer timer = new Timer();
|
||||
TimerTask lTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (call == null) {
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
final LinphoneCallStats audioStats = call.getAudioStats();
|
||||
if (audioStats != null) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
TextView codec = (TextView) view.findViewById(R.id.audioCodec);
|
||||
TextView dl = (TextView) view.findViewById(R.id.audioDownloadBandwith);
|
||||
TextView ul = (TextView) view.findViewById(R.id.audioUploadBandwith);
|
||||
TextView ice = (TextView) view.findViewById(R.id.ice);
|
||||
if (codec == null || dl == null || ul == null || ice == null) {
|
||||
timer.cancel();
|
||||
return;
|
||||
}
|
||||
codec.setText(call.getCurrentParamsCopy().getUsedAudioCodec().getMime());
|
||||
dl.setText(String.valueOf((int) audioStats.getDownloadBandwidth()) + " kbits/s");
|
||||
ul.setText(String.valueOf((int) audioStats.getUploadBandwidth()) + " kbits/s");
|
||||
ice.setText(audioStats.getIceState().toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(lTask, 0, 1500);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void initFlipperListeners(final ViewFlipper flipper) {
|
||||
SwipeListener swipeListener = new SwipeListener() {
|
||||
int currentView = FLIPPER_AVATAR_VIEW;
|
||||
|
||||
@Override
|
||||
public void onLeftToRightSwipe() {
|
||||
if (currentView == FLIPPER_AVATAR_VIEW) {
|
||||
currentView = FLIPPER_AUDIO_STATS_VIEW;
|
||||
} else {
|
||||
currentView = FLIPPER_AVATAR_VIEW;
|
||||
}
|
||||
flipper.setDisplayedChild(currentView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRightToLeftSwipe() {
|
||||
if (currentView == FLIPPER_AUDIO_STATS_VIEW) {
|
||||
currentView = FLIPPER_AVATAR_VIEW;
|
||||
} else {
|
||||
currentView = FLIPPER_AUDIO_STATS_VIEW;
|
||||
}
|
||||
flipper.setDisplayedChild(currentView);
|
||||
}
|
||||
};
|
||||
flipper.setOnTouchListener(new SwipeGestureDetector(swipeListener));
|
||||
}
|
||||
|
||||
private void setRowBackgroundAndPadding(LinearLayout callView, Resources resources, int index, LinphoneCall call, boolean active) {
|
||||
|
@ -265,4 +357,48 @@ public class AudioCallFragment extends Fragment implements OnClickListener {
|
|||
|
||||
callsList.invalidate();
|
||||
}
|
||||
|
||||
class SwipeGestureDetector implements OnTouchListener {
|
||||
static final int MIN_DISTANCE = 100;
|
||||
private float downX, upX;
|
||||
private boolean lock;
|
||||
|
||||
private SwipeListener listener;
|
||||
|
||||
public SwipeGestureDetector(SwipeListener swipeListener) {
|
||||
super();
|
||||
listener = swipeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
switch(event.getAction()){
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
lock = false;
|
||||
downX = event.getX();
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (lock) {
|
||||
return false;
|
||||
}
|
||||
upX = event.getX();
|
||||
|
||||
float deltaX = downX - upX;
|
||||
|
||||
if (Math.abs(deltaX) > MIN_DISTANCE) {
|
||||
lock = true;
|
||||
if (deltaX < 0) { listener.onLeftToRightSwipe(); return true; }
|
||||
if (deltaX > 0) { listener.onRightToLeftSwipe(); return true; }
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
interface SwipeListener {
|
||||
void onRightToLeftSwipe();
|
||||
void onLeftToRightSwipe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -494,13 +494,13 @@ public final class LinphoneManager implements LinphoneCoreListener {
|
|||
} catch (LinphoneException e) {
|
||||
Log.w("no config ready yet");
|
||||
}
|
||||
|
||||
TimerTask lTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
mLc.iterate();
|
||||
}
|
||||
};
|
||||
|
||||
mTimer.scheduleAtFixedRate(lTask, 0, 20);
|
||||
|
||||
IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
|
||||
|
|
Loading…
Reference in a new issue