Java tutorial
package co.taqat.call; /* StatusFragment.java Copyright (C) 2012 Belledonne Communications, Grenoble, France 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import java.text.DecimalFormat; import java.util.Timer; import java.util.TimerTask; import co.taqat.call.assistant.AssistantActivity; import org.linphone.core.LinphoneAccountCreator; import org.linphone.core.LinphoneCall; import org.linphone.core.LinphoneCallParams; import org.linphone.core.LinphoneCallStats; import org.linphone.core.LinphoneCallStats.LinphoneAddressFamily; import org.linphone.core.LinphoneContent; import org.linphone.core.LinphoneCore; import org.linphone.core.LinphoneCore.MediaEncryption; import org.linphone.core.LinphoneCore.RegistrationState; import org.linphone.core.LinphoneCoreListenerBase; import org.linphone.core.LinphoneEvent; import org.linphone.core.LinphoneProxyConfig; import org.linphone.core.PayloadType; import org.linphone.mediastream.Log; import android.app.Activity; import android.app.Dialog; import android.app.Fragment; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.support.v4.content.ContextCompat; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; /** * @author Sylvain Berfini */ public class StatusFragment extends Fragment { private Handler mHandler = new Handler(); private Handler refreshHandler = new Handler(); private TextView statusText, voicemailCount; private ImageView statusLed, callQuality, encryption, menu, voicemail; private Runnable mCallQualityUpdater; private boolean isInCall, isAttached = false; private Timer mTimer; private TimerTask mTask; private LinphoneCoreListenerBase mListener; private Dialog ZRTPdialog = null; private int mDisplayedQuality = -1; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.status, container, false); statusText = (TextView) view.findViewById(R.id.status_text); statusLed = (ImageView) view.findViewById(R.id.status_led); callQuality = (ImageView) view.findViewById(R.id.call_quality); encryption = (ImageView) view.findViewById(R.id.encryption); menu = (ImageView) view.findViewById(R.id.side_menu_button); voicemail = (ImageView) view.findViewById(R.id.voicemail); voicemailCount = (TextView) view.findViewById(R.id.voicemail_count); // We create it once to not delay the first display populateSliderContent(); mListener = new LinphoneCoreListenerBase() { @Override public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig proxy, final LinphoneCore.RegistrationState state, String smessage) { if (!isAttached || !LinphoneService.isReady()) { return; } if (lc.getProxyConfigList() == null) { statusLed.setImageResource(R.drawable.led_disconnected); statusText.setText(getString(R.string.no_account)); } else { statusLed.setVisibility(View.VISIBLE); } if (lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().equals(proxy)) { statusLed.setImageResource(getStatusIconResource(state, true)); statusText.setText(getStatusIconText(state)); } else if (lc.getDefaultProxyConfig() == null) { statusLed.setImageResource(getStatusIconResource(state, true)); statusText.setText(getStatusIconText(state)); } try { statusText.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!isInCall) { lc.refreshRegisters(); /*try { Thread.sleep(2000); } catch (InterruptedException e) { Log.e("Cannot sleep for 2s", e); }*/ } } }); } catch (IllegalStateException ise) { Log.e("ReRegisteration ERROR : ", ise.getMessage()); } } @Override public void notifyReceived(LinphoneCore lc, LinphoneEvent ev, String eventName, LinphoneContent content) { if (!content.getType().equals("application")) return; if (!content.getSubtype().equals("simple-message-summary")) return; if (content.getData() == null) return; int unreadCount = -1; String data = content.getDataAsString(); String[] voiceMail = data.split("voice-message: "); final String[] intToParse = voiceMail[1].split("/", 0); unreadCount = Integer.parseInt(intToParse[0]); if (unreadCount > 0) { voicemailCount.setText(unreadCount); voicemail.setVisibility(View.VISIBLE); voicemailCount.setVisibility(View.VISIBLE); } else { voicemail.setVisibility(View.GONE); voicemailCount.setVisibility(View.GONE); } } }; isAttached = true; Activity activity = getActivity(); if (activity instanceof LinphoneActivity) { ((LinphoneActivity) activity).updateStatusFragment(this); isInCall = false; } else if (activity instanceof CallActivity) { ((CallActivity) activity).updateStatusFragment(this); isInCall = true; } else if (activity instanceof AssistantActivity) { ((AssistantActivity) activity).updateStatusFragment(this); isInCall = false; } return view; } public void setLinphoneCoreListener() { LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); if (lc != null) { lc.addListener(mListener); LinphoneProxyConfig lpc = lc.getDefaultProxyConfig(); if (lpc != null) { mListener.registrationState(lc, lpc, lpc.getState(), null); } } } @Override public void onDetach() { super.onDetach(); isAttached = false; } //NORMAL STATUS BAR private void populateSliderContent() { if (LinphoneManager.isInstanciated() && LinphoneManager.getLc() != null) { voicemailCount.setVisibility(View.GONE); if (isInCall && isAttached) { //LinphoneCall call = LinphoneManager.getLc().getCurrentCall(); //initCallStatsRefresher(call, callStats); } else if (!isInCall) { voicemailCount.setVisibility(View.VISIBLE); } if (LinphoneManager.getLc().getProxyConfigList().length == 0) { statusLed.setImageResource(R.drawable.led_disconnected); statusText.setText(getString(R.string.no_account)); } } } public void resetAccountStatus() { if (LinphoneManager.getLc().getProxyConfigList().length == 0) { statusLed.setImageResource(R.drawable.led_disconnected); statusText.setText(getString(R.string.no_account)); } } public void enableSideMenu(boolean enabled) { menu.setEnabled(enabled); } private int getStatusIconResource(LinphoneCore.RegistrationState state, boolean isDefaultAccount) { try { LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); boolean defaultAccountConnected = (isDefaultAccount && lc != null && lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().isRegistered()) || !isDefaultAccount; if (state == RegistrationState.RegistrationOk && defaultAccountConnected) { return R.drawable.led_connected; } else if (state == RegistrationState.RegistrationProgress) { return R.drawable.led_inprogress; } else if (state == RegistrationState.RegistrationFailed) { return R.drawable.led_error; } else { return R.drawable.led_disconnected; } } catch (Exception e) { Log.e(e); } return R.drawable.led_disconnected; } private String getStatusIconText(LinphoneCore.RegistrationState state) { Context context = getActivity(); if (!isAttached && LinphoneActivity.isInstanciated()) context = LinphoneActivity.instance(); else if (!isAttached && LinphoneService.isReady()) context = LinphoneService.instance(); try { if (state == RegistrationState.RegistrationOk && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getDefaultProxyConfig().isRegistered()) { return context.getString(R.string.status_connected); } else if (state == RegistrationState.RegistrationProgress) { return context.getString(R.string.status_in_progress); } else if (state == RegistrationState.RegistrationFailed) { return context.getString(R.string.status_error); } else { return context.getString(R.string.status_not_connected); } } catch (Exception e) { Log.e("ERRRORR", e.getMessage()); } return context.getString(R.string.status_not_connected); } //INCALL STATUS BAR private void startCallQuality() { callQuality.setVisibility(View.VISIBLE); refreshHandler.postDelayed(mCallQualityUpdater = new Runnable() { LinphoneCall mCurrentCall = LinphoneManager.getLc().getCurrentCall(); public void run() { if (mCurrentCall == null) { mCallQualityUpdater = null; return; } float newQuality = mCurrentCall.getCurrentQuality(); updateQualityOfSignalIcon(newQuality); if (isInCall) { refreshHandler.postDelayed(this, 1000); } else mCallQualityUpdater = null; } }, 1000); } void updateQualityOfSignalIcon(float quality) { int iQuality = (int) quality; if (iQuality == mDisplayedQuality) return; if (quality >= 4) // Good Quality { callQuality.setImageResource(R.drawable.call_quality_indicator_4); } else if (quality >= 3) // Average quality { callQuality.setImageResource(R.drawable.call_quality_indicator_3); } else if (quality >= 2) // Low quality { callQuality.setImageResource(R.drawable.call_quality_indicator_2); } else if (quality >= 1) // Very low quality { callQuality.setImageResource(R.drawable.call_quality_indicator_1); } else // Worst quality { callQuality.setImageResource(R.drawable.call_quality_indicator_0); } mDisplayedQuality = iQuality; } @Override public void onResume() { super.onResume(); LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); if (lc != null) { lc.addListener(mListener); LinphoneProxyConfig lpc = lc.getDefaultProxyConfig(); if (lpc != null) { mListener.registrationState(lc, lpc, lpc.getState(), null); } LinphoneCall call = lc.getCurrentCall(); if (isInCall && (call != null || lc.getConferenceSize() > 1 || lc.getCallsNb() > 0)) { if (call != null) { startCallQuality(); refreshStatusItems(call, call.getCurrentParamsCopy().getVideoEnabled()); } menu.setVisibility(View.INVISIBLE); encryption.setVisibility(View.VISIBLE); callQuality.setVisibility(View.VISIBLE); // We are obviously connected if (lc.getDefaultProxyConfig() == null) { statusLed.setImageResource(R.drawable.led_disconnected); statusText.setText(getString(R.string.no_account)); } else { statusLed.setImageResource(getStatusIconResource(lc.getDefaultProxyConfig().getState(), true)); statusText.setText(getStatusIconText(lc.getDefaultProxyConfig().getState())); } } } else { statusText.setVisibility(View.VISIBLE); encryption.setVisibility(View.GONE); } } @Override public void onPause() { super.onPause(); LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); if (lc != null) { lc.removeListener(mListener); } if (mCallQualityUpdater != null) { refreshHandler.removeCallbacks(mCallQualityUpdater); mCallQualityUpdater = null; } } public void refreshStatusItems(final LinphoneCall call, boolean isVideoEnabled) { if (call != null) { voicemailCount.setVisibility(View.GONE); MediaEncryption mediaEncryption = call.getCurrentParamsCopy().getMediaEncryption(); if (isVideoEnabled) { //background.setVisibility(View.GONE); } else { //background.setVisibility(View.VISIBLE); } if (mediaEncryption == MediaEncryption.SRTP || (mediaEncryption == MediaEncryption.ZRTP && call.isAuthenticationTokenVerified()) || mediaEncryption == MediaEncryption.DTLS) { encryption.setImageResource(R.drawable.security_ok); } else if (mediaEncryption == MediaEncryption.ZRTP && !call.isAuthenticationTokenVerified()) { encryption.setImageResource(R.drawable.security_pending); } else { encryption.setImageResource(R.drawable.security_ko); } if (mediaEncryption == MediaEncryption.ZRTP) { encryption.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { showZRTPDialog(call); } }); } else { encryption.setOnClickListener(null); } } } public void showZRTPDialog(final LinphoneCall call) { if (getActivity() == null) { Log.w("Can't display ZRTP popup, no Activity"); return; } if (ZRTPdialog == null || !ZRTPdialog.isShowing()) { ZRTPdialog = new Dialog(getActivity()); ZRTPdialog.requestWindowFeature(Window.FEATURE_NO_TITLE); Drawable d = new ColorDrawable(ContextCompat.getColor(getActivity(), R.color.colorC)); d.setAlpha(200); ZRTPdialog.setContentView(R.layout.dialog); ZRTPdialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); ZRTPdialog.getWindow().setBackgroundDrawable(d); TextView customText = (TextView) ZRTPdialog.findViewById(R.id.customText); String newText = getString(R.string.zrtp_dialog).replace("%s", call.getAuthenticationToken()); customText.setText(newText); Button delete = (Button) ZRTPdialog.findViewById(R.id.delete_button); delete.setText(R.string.accept); Button cancel = (Button) ZRTPdialog.findViewById(R.id.cancel); cancel.setText(R.string.deny); delete.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { call.setAuthenticationTokenVerified(true); if (encryption != null) { encryption.setImageResource(R.drawable.security_ok); } ZRTPdialog.dismiss(); } }); cancel.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { if (call != null) { call.setAuthenticationTokenVerified(false); if (encryption != null) { encryption.setImageResource(R.drawable.security_ko); } } ZRTPdialog.dismiss(); } }); ZRTPdialog.show(); } } private void formatText(TextView tv, String name, String value) { tv.setText(Html.fromHtml("<b>" + name + " </b>" + value)); } private void displayMediaStats(LinphoneCallParams params, LinphoneCallStats stats, PayloadType media, View layout, TextView title, TextView codec, TextView dl, TextView ul, TextView ice, TextView ip, TextView senderLossRate, TextView receiverLossRate, TextView enc, TextView dec, TextView videoResolutionSent, TextView videoResolutionReceived, boolean isVideo) { Context ctxt = LinphoneActivity.instance(); if (stats != null) { layout.setVisibility(View.VISIBLE); title.setVisibility(TextView.VISIBLE); if (media != null) { String mime = media.getMime(); if (LinphoneManager.getLc().openH264Enabled() && media.getMime().equals("H264") && LinphoneManager.getInstance().getOpenH264DownloadHelper().isCodecFound()) { mime = "OpenH264"; } formatText(codec, ctxt.getString(R.string.call_stats_codec), mime + " / " + (media.getRate() / 1000) + "kHz"); } formatText(enc, ctxt.getString(R.string.call_stats_encoder_name), stats.getEncoderName(media)); formatText(dec, ctxt.getString(R.string.call_stats_decoder_name), stats.getDecoderName(media)); formatText(dl, ctxt.getString(R.string.call_stats_download), String.valueOf((int) stats.getDownloadBandwidth()) + " kbits/s"); formatText(ul, ctxt.getString(R.string.call_stats_upload), String.valueOf((int) stats.getUploadBandwidth()) + " kbits/s"); formatText(ice, ctxt.getString(R.string.call_stats_ice), stats.getIceState().toString()); formatText(ip, ctxt.getString(R.string.call_stats_ip), (stats.getIpFamilyOfRemote() == LinphoneAddressFamily.INET_6.getInt()) ? "IpV6" : (stats.getIpFamilyOfRemote() == LinphoneAddressFamily.INET.getInt()) ? "IpV4" : "Unknown"); formatText(senderLossRate, ctxt.getString(R.string.call_stats_sender_loss_rate), new DecimalFormat("##.##").format(stats.getSenderLossRate()) + "%"); formatText(receiverLossRate, ctxt.getString(R.string.call_stats_receiver_loss_rate), new DecimalFormat("##.##").format(stats.getReceiverLossRate()) + "%"); if (isVideo) { formatText(videoResolutionSent, ctxt.getString(R.string.call_stats_video_resolution_sent), "\u2191 " + params.getSentVideoSize().toDisplayableString()); formatText(videoResolutionReceived, ctxt.getString(R.string.call_stats_video_resolution_received), "\u2193 " + params.getReceivedVideoSize().toDisplayableString()); } } else { layout.setVisibility(View.GONE); title.setVisibility(TextView.GONE); } layout.setVisibility(View.GONE); title.setVisibility(TextView.GONE); } public void initCallStatsRefresher(final LinphoneCall call, final View view) { if (mTimer != null && mTask != null) { return; } mTimer = new Timer(); mTask = new TimerTask() { @Override public void run() { if (call == null) { mTimer.cancel(); return; } final TextView titleAudio = (TextView) view.findViewById(R.id.call_stats_audio); final TextView titleVideo = (TextView) view.findViewById(R.id.call_stats_video); final TextView codecAudio = (TextView) view.findViewById(R.id.codec_audio); final TextView codecVideo = (TextView) view.findViewById(R.id.codec_video); final TextView encoderAudio = (TextView) view.findViewById(R.id.encoder_audio); final TextView decoderAudio = (TextView) view.findViewById(R.id.decoder_audio); final TextView encoderVideo = (TextView) view.findViewById(R.id.encoder_video); final TextView decoderVideo = (TextView) view.findViewById(R.id.decoder_video); final TextView dlAudio = (TextView) view.findViewById(R.id.downloadBandwith_audio); final TextView ulAudio = (TextView) view.findViewById(R.id.uploadBandwith_audio); final TextView dlVideo = (TextView) view.findViewById(R.id.downloadBandwith_video); final TextView ulVideo = (TextView) view.findViewById(R.id.uploadBandwith_video); final TextView iceAudio = (TextView) view.findViewById(R.id.ice_audio); final TextView iceVideo = (TextView) view.findViewById(R.id.ice_video); final TextView videoResolutionSent = (TextView) view.findViewById(R.id.video_resolution_sent); final TextView videoResolutionReceived = (TextView) view .findViewById(R.id.video_resolution_received); final TextView senderLossRateAudio = (TextView) view.findViewById(R.id.senderLossRateAudio); final TextView receiverLossRateAudio = (TextView) view.findViewById(R.id.receiverLossRateAudio); final TextView senderLossRateVideo = (TextView) view.findViewById(R.id.senderLossRateVideo); final TextView receiverLossRateVideo = (TextView) view.findViewById(R.id.receiverLossRateVideo); final TextView ipAudio = (TextView) view.findViewById(R.id.ip_audio); final TextView ipVideo = (TextView) view.findViewById(R.id.ip_video); final View videoLayout = view.findViewById(R.id.callStatsVideo); final View audioLayout = view.findViewById(R.id.callStatsAudio); if (titleAudio == null || codecAudio == null || dlVideo == null || iceAudio == null || videoResolutionSent == null || videoLayout == null || titleVideo == null || ipVideo == null || ipAudio == null || codecVideo == null || dlAudio == null || ulAudio == null || ulVideo == null || iceVideo == null || videoResolutionReceived == null) { mTimer.cancel(); return; } mHandler.post(new Runnable() { @Override public void run() { synchronized (LinphoneManager.getLc()) { if (LinphoneActivity.isInstanciated()) { LinphoneCallParams params = call.getCurrentParamsCopy(); if (params != null) { LinphoneCallStats audioStats = call.getAudioStats(); LinphoneCallStats videoStats = null; if (params.getVideoEnabled()) videoStats = call.getVideoStats(); PayloadType payloadAudio = params.getUsedAudioCodec(); PayloadType payloadVideo = params.getUsedVideoCodec(); displayMediaStats(params, audioStats, payloadAudio, audioLayout, titleAudio, codecAudio, dlAudio, ulAudio, iceAudio, ipAudio, senderLossRateAudio, receiverLossRateAudio, encoderAudio, decoderAudio, null, null, false); displayMediaStats(params, videoStats, payloadVideo, videoLayout, titleVideo, codecVideo, dlVideo, ulVideo, iceVideo, ipVideo, senderLossRateVideo, receiverLossRateVideo, encoderVideo, decoderVideo, videoResolutionSent, videoResolutionReceived, true); } } } } }); } }; mTimer.scheduleAtFixedRate(mTask, 0, 1000); } }