Java tutorial
/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple 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. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple 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 CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ package com.abcvoipsip.ui.prefs; import android.app.AlertDialog; import android.content.DialogInterface; import android.graphics.Color; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.view.MenuItem; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.view.ContextMenu; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView; import android.widget.ImageView; import android.widget.SimpleAdapter; import android.widget.SimpleAdapter.ViewBinder; import android.widget.TextView; import com.abcvoipsip.R; import com.abcvoipsip.utils.Log; import com.abcvoipsip.utils.PreferencesWrapper; import com.abcvoipsip.widgets.DragnDropListView; import com.abcvoipsip.widgets.DragnDropListView.DropListener; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; public class CodecsFragment extends ListFragment { protected static final String THIS_FILE = "CodecsFragment"; private static final String CODEC_NAME = "codec_name"; private static final String CODEC_ID = "codec_id"; private static final String CODEC_PRIORITY = "codec_priority"; public static final String BAND_TYPE = "band_type"; public static final String MEDIA_TYPE = "media_type"; public static final int MEDIA_AUDIO = 0; public static final int MEDIA_VIDEO = 1; public static final int MENU_ITEM_ACTIVATE = Menu.FIRST + 1; private SimpleAdapter mAdapter; private List<Map<String, Object>> codecsList; private PreferencesWrapper prefsWrapper; // Type for codec bandwidth private String bandtype; // Type for media (audio/video) private Integer mediatype; private static final Map<String, String> NON_FREE_CODECS = new HashMap<String, String>(); static { NON_FREE_CODECS.put("G729/8000/1", "http://www.synapseglobal.com/g729_codec_license.html"); }; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); prefsWrapper = new PreferencesWrapper(getActivity()); initDatas(); setHasOptionsMenu(true); // Adapter mAdapter = new SimpleAdapter(getActivity(), codecsList, R.layout.codecs_list_item, new String[] { CODEC_NAME, CODEC_PRIORITY }, new int[] { R.id.line1, R.id.entiere_line }); mAdapter.setViewBinder(new ViewBinder() { @Override public boolean setViewValue(View view, Object data, String textRepresentation) { if (view.getId() == R.id.entiere_line) { Log.d(THIS_FILE, "Entiere line is binded "); TextView tv = (TextView) view.findViewById(R.id.line1); ImageView grabber = (ImageView) view.findViewById(R.id.icon); if ((Short) data == 0) { tv.setTextColor(Color.GRAY); grabber.setImageResource(R.drawable.ic_mp_disabled); } else { tv.setTextColor(Color.WHITE); grabber.setImageResource(R.drawable.ic_mp_move); } return true; } return false; } }); setListAdapter(mAdapter); registerForContextMenu(getListView()); } /** * Initialize datas list */ private void initDatas() { if (codecsList == null) { codecsList = new ArrayList<Map<String, Object>>(); } else { codecsList.clear(); } bandtype = (String) getArguments().get(BAND_TYPE); mediatype = (Integer) getArguments().get(MEDIA_TYPE); String[] codecNames; if (mediatype == MEDIA_AUDIO) { codecNames = prefsWrapper.getCodecList(); } else { codecNames = prefsWrapper.getVideoCodecList(); } int current_prio = 130; for (String codecName : codecNames) { Log.d(THIS_FILE, "Fill codec " + codecName + " for " + bandtype); String[] codecParts = codecName.split("/"); if (codecParts.length >= 2) { HashMap<String, Object> codecInfo = new HashMap<String, Object>(); codecInfo.put(CODEC_ID, codecName); if (mediatype == MEDIA_AUDIO) { codecInfo.put(CODEC_NAME, codecParts[0] + " " + codecParts[1].substring(0, codecParts[1].length() - 3) + " kHz"); } else if (mediatype == MEDIA_VIDEO) { codecInfo.put(CODEC_NAME, codecParts[0]); } codecInfo.put(CODEC_PRIORITY, prefsWrapper.getCodecPriority(codecName, bandtype, Integer.toString(current_prio))); codecsList.add(codecInfo); current_prio--; Log.d(THIS_FILE, "Found priority is " + codecInfo.get(CODEC_PRIORITY)); } } Collections.sort(codecsList, codecsComparator); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.codecs_list, container, false); DragnDropListView listView = (DragnDropListView) v.findViewById(android.R.id.list); listView.setOnDropListener(new DropListener() { @Override public void drop(int from, int to) { @SuppressWarnings("unchecked") HashMap<String, Object> item = (HashMap<String, Object>) getListAdapter().getItem(from); Log.d(THIS_FILE, "Dropped " + item.get(CODEC_NAME) + " -> " + to); //Prevent disabled codecsList to be reordered if ((Short) item.get(CODEC_PRIORITY) <= 0) { return; } codecsList.remove(from); codecsList.add(to, item); //Update priorities short currentPriority = 130; for (Map<String, Object> codec : codecsList) { if ((Short) codec.get(CODEC_PRIORITY) > 0) { if (currentPriority != (Short) codec.get(CODEC_PRIORITY)) { prefsWrapper.setCodecPriority((String) codec.get(CODEC_ID), bandtype, Short.toString(currentPriority)); codec.put(CODEC_PRIORITY, currentPriority); } //Log.d(THIS_FILE, "Reorder : "+codec.toString()); currentPriority--; } } //Log.d(THIS_FILE, "Data set "+codecsList.toString()); mAdapter.notifyDataSetChanged(); } }); listView.setOnCreateContextMenuListener(this); return v; } @Override @SuppressWarnings("unchecked") public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) menuInfo; } catch (ClassCastException e) { Log.e(THIS_FILE, "bad menuInfo", e); return; } HashMap<String, Object> codec = (HashMap<String, Object>) mAdapter.getItem(info.position); if (codec == null) { // If for some reason the requested item isn't available, do nothing return; } boolean isDisabled = ((Short) codec.get(CODEC_PRIORITY) == 0); menu.add(0, MENU_ITEM_ACTIVATE, 0, isDisabled ? R.string.activate : R.string.deactivate); } @Override @SuppressWarnings("unchecked") public boolean onContextItemSelected(MenuItem item) { AdapterView.AdapterContextMenuInfo info; try { info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo(); } catch (ClassCastException e) { Log.e(THIS_FILE, "bad menuInfo", e); return false; } HashMap<String, Object> codec = null; codec = (HashMap<String, Object>) mAdapter.getItem(info.position); if (codec == null) { // If for some reason the requested item isn't available, do nothing return false; } int selId = item.getItemId(); if (selId == MENU_ITEM_ACTIVATE) { boolean isDisabled = ((Short) codec.get(CODEC_PRIORITY) == 0); final short newPrio = isDisabled ? (short) 1 : (short) 0; if (NON_FREE_CODECS.containsKey(codec.get(CODEC_ID)) && isDisabled) { final HashMap<String, Object> fCodec = codec; final TextView message = new TextView(getActivity()); final SpannableString s = new SpannableString( getString(R.string.this_codec_is_not_free) + NON_FREE_CODECS.get(codec.get(CODEC_ID))); Linkify.addLinks(s, Linkify.WEB_URLS); message.setText(s); message.setMovementMethod(LinkMovementMethod.getInstance()); message.setPadding(10, 10, 10, 10); //Alert user that we will disable for all incoming calls as he want to quit new AlertDialog.Builder(getActivity()).setTitle(R.string.warning).setView(message) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { setCodecActivated(fCodec, newPrio); } }).setNegativeButton(R.string.cancel, null).show(); } else { setCodecActivated(codec, newPrio); } return true; } return false; } /** * Internal method to activate codec priority * @param codec the codec to activate * @param newPrio the new priority of the codec (0 to disable) */ private void setCodecActivated(Map<String, Object> codec, short newPrio) { codec.put(CODEC_PRIORITY, newPrio); prefsWrapper.setCodecPriority((String) codec.get(CODEC_ID), bandtype, Short.toString(newPrio)); Collections.sort(codecsList, codecsComparator); mAdapter.notifyDataSetChanged(); } /** * Class to compare the codecs based on their priority */ private final Comparator<Map<String, Object>> codecsComparator = new Comparator<Map<String, Object>>() { @Override public int compare(Map<String, Object> infos1, Map<String, Object> infos2) { if (infos1 != null && infos2 != null) { short c1 = (Short) infos1.get(CODEC_PRIORITY); short c2 = (Short) infos2.get(CODEC_PRIORITY); if (c1 > c2) { return -1; } if (c1 < c2) { return 1; } } return 0; } }; }