/* * TeleStax, Open Source Cloud Communications * Copyright 2011-2015, Telestax Inc and individual contributors * by the @authors tag. * * This program is free software: you can redistribute it and/or modify * under the terms of the GNU Affero 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * * For questions related to commercial use licensing, please contact sales@telestax.com. * */ package org.restcomm.android.olympus; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.BitmapDrawable; import android.media.AudioManager; import android.media.ToneGenerator; import android.os.Bundle; import android.app.Fragment; import android.os.Handler; import android.renderscript.Allocation; import android.renderscript.Element; import android.renderscript.RenderScript; import android.renderscript.ScriptIntrinsicBlur; import android.support.v7.widget.AppCompatImageButton; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ImageButton; import android.widget.ImageView; import org.restcomm.android.sdk.RCConnection; import org.restcomm.android.sdk.RCDevice; public class KeypadFragment extends Fragment implements View.OnTouchListener { // TODO: Rename parameter arguments, choose names that match // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER private static final String ARG_PARAM1 = "param1"; private static final String ARG_PARAM2 = "param2"; private static final String TAG = "KeypadFragment"; private View controlView; private RCConnection connection; //private Bitmap screenshotBitmap; private ToneGenerator toneGenerator; ImageButton btnOne; ImageButton btnTwo; ImageButton btnThree; ImageButton btnFour; ImageButton btnFive; ImageButton btnSix; ImageButton btnSeven; ImageButton btnEight; ImageButton btnNine; ImageButton btnZero; ImageButton btnHash; ImageButton btnStar; ImageButton btnCancel; ImageView backgroundView; // TODO: Rename and change types of parameters private String mParam1; private String mParam2; private OnFragmentInteractionListener mListener; /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param param1 Parameter 1. * @param param2 Parameter 2. * @return A new instance of fragment KeypadFragment. */ // TODO: Rename and change types and number of parameters public static KeypadFragment newInstance(String param1, String param2) { Log.i(TAG, "%% newInstance"); KeypadFragment fragment = new KeypadFragment(); Bundle args = new Bundle(); args.putString(ARG_PARAM1, param1); args.putString(ARG_PARAM2, param2); fragment.setArguments(args); return fragment; } public KeypadFragment() { // Required empty public constructor } @Override public void onCreate(Bundle savedInstanceState) { Log.i(TAG, "%% onCreate"); super.onCreate(savedInstanceState); if (getArguments() != null) { mParam1 = getArguments().getString(ARG_PARAM1); mParam2 = getArguments().getString(ARG_PARAM2); } toneGenerator = new ToneGenerator(AudioManager.STREAM_MUSIC, 100); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i(TAG, "%% onCreateView"); controlView = inflater.inflate(R.layout.fragment_keypad, container, false); btnOne = (ImageButton) controlView.findViewById(R.id.imageButton_1); btnOne.setOnTouchListener(this); btnTwo = (ImageButton) controlView.findViewById(R.id.imageButton_2); btnTwo.setOnTouchListener(this); btnThree = (ImageButton) controlView.findViewById(R.id.imageButton_3); btnThree.setOnTouchListener(this); btnFour = (ImageButton) controlView.findViewById(R.id.imageButton_4); btnFour.setOnTouchListener(this); btnFive = (ImageButton) controlView.findViewById(R.id.imageButton_5); btnFive.setOnTouchListener(this); btnSix = (ImageButton) controlView.findViewById(R.id.imageButton_6); btnSix.setOnTouchListener(this); btnSeven = (ImageButton) controlView.findViewById(R.id.imageButton_7); btnSeven.setOnTouchListener(this); btnEight = (ImageButton) controlView.findViewById(R.id.imageButton_8); btnEight.setOnTouchListener(this); btnNine = (ImageButton) controlView.findViewById(R.id.imageButton_9); btnNine.setOnTouchListener(this); btnZero = (ImageButton) controlView.findViewById(R.id.imageButton_0); btnZero.setOnTouchListener(this); btnStar = (ImageButton) controlView.findViewById(R.id.imageButton_star); btnStar.setOnTouchListener(this); btnHash = (ImageButton) controlView.findViewById(R.id.imageButton_hash); btnHash.setOnTouchListener(this); btnCancel = (ImageButton) controlView.findViewById(R.id.button_cancel); btnCancel.setOnTouchListener(this); backgroundView = (ImageView)controlView.findViewById(R.id.backgroundView); // Inflate the layout for this fragment return controlView; } @Override public void onStart() { super.onStart(); Log.i(TAG, "%% onStart"); } @Override public void onStop() { super.onStop(); Log.i(TAG, "%% onStop"); } @Override public void onResume() { super.onResume(); Log.i(TAG, "%% onResume"); } @Override public void onHiddenChanged(boolean hidden) { super.onHiddenChanged(hidden); Log.i(TAG, "%% onHiddenChanged"); // The idea here was to create a variable alpha bitmap, to give a nice cloudy effect where // other areas are more and others are less concealed from the background (i.e. call). Turned out // to be a big pain so I'm leaving out for now /* if (!hidden) { // Need to defer a bit as the view is not yet ready and the bitmap creation breaks (TODO: need to find a proper event for that) Handler handler = new Handler(); // schedule a registration update after 'registrationRefresh' seconds Runnable runnable = new Runnable() { @Override public void run() { //Bitmap bitmap = getScreenShot(backgroundView); //Bitmap blurredBitmap = blurBitmap(bitmap); //backgroundView.setImageBitmap(blurredBitmap); final BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.ARGB_8888; options.inScaled = false; // Load source grayscale bitmap Bitmap grayscale = BitmapFactory.decodeResource(getResources(), R.drawable.dtmf_pattern, options); // Place for alpha mask. It's specifically ARGB_8888 not ALPHA_8, // ALPHA_8 for some reason didn't work out for me. Bitmap alpha = Bitmap.createBitmap(grayscale.getWidth(), grayscale.getHeight(), Bitmap.Config.ARGB_8888); float[] matrix = new float[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 }; Paint grayToAlpha = new Paint(); grayToAlpha.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(matrix))); Canvas alphaCanvas = new Canvas(alpha); // Make sure nothing gets scaled during drawing alphaCanvas.setDensity(Bitmap.DENSITY_NONE); // Draw grayscale bitmap on to alpha canvas, using color filter that // takes alpha from red channel alphaCanvas.drawBitmap(grayscale, 0, 0, grayToAlpha); // Bitmap alpha now has usable alpha channel! backgroundView.setBackground(new BitmapDrawable(getResources(), alpha)); } }; handler.postDelayed(runnable, 0); } */ } @Override public void onPause() { super.onPause(); Log.i(TAG, "%% onPause"); } @Override public void onAttach(Activity activity) { Log.i(TAG, "%% onAttach"); super.onAttach(activity); try { mListener = (OnFragmentInteractionListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener"); } } @Override public void onDetach() { Log.i(TAG, "%% onDetach"); super.onDetach(); mListener = null; } public boolean onTouch(View v, MotionEvent e) { switch (e.getAction()) { case MotionEvent.ACTION_DOWN: { if (v.getId() == R.id.imageButton_1) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_1, 300); connection.sendDigits("1"); } else if (v.getId() == R.id.imageButton_2) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_2, 300); connection.sendDigits("2"); } else if (v.getId() == R.id.imageButton_3) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_3, 300); connection.sendDigits("3"); } else if (v.getId() == R.id.imageButton_4) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_4, 300); connection.sendDigits("4"); } else if (v.getId() == R.id.imageButton_5) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_5, 300); connection.sendDigits("5"); } else if (v.getId() == R.id.imageButton_6) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_6, 300); connection.sendDigits("6"); } else if (v.getId() == R.id.imageButton_7) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_7, 300); connection.sendDigits("7"); } else if (v.getId() == R.id.imageButton_8) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_8, 300); connection.sendDigits("8"); } else if (v.getId() == R.id.imageButton_9) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_9, 300); connection.sendDigits("9"); } else if (v.getId() == R.id.imageButton_0) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_0, 300); connection.sendDigits("0"); } else if (v.getId() == R.id.imageButton_star) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_S, 300); connection.sendDigits("*"); } else if (v.getId() == R.id.imageButton_hash) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_P, 300); connection.sendDigits("#"); } else if (v.getId() == R.id.button_cancel) { mListener.onFragmentInteraction("cancel"); } // Add also visual feedback as long as the user keeps the button pressed v.setBackgroundResource(R.drawable.pressed_digit); v.invalidate(); break; } case MotionEvent.ACTION_UP: // Your action here on button click case MotionEvent.ACTION_CANCEL: { final View view = v; // add small delay to make sure it is perceivable even for very fast touches new Handler().postDelayed(new Runnable() { @Override public void run() { view.setBackgroundResource(0); view.invalidate(); } }, 100); break; } } return true; } /* btnOne.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { //btnOne.getBackground().setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); view.setBackgroundResource(R.drawable.pressed_digit); //btnOne.setBac view.invalidate(); break; } case MotionEvent.ACTION_UP: // Your action here on button click case MotionEvent.ACTION_CANCEL: { //view.getBackground().clearColorFilter(); view.setBackgroundResource(0); view.invalidate(); break; } } return true; } }); */ /* @Override public void onClick(View v) { if (v.getId() == R.id.imageButton_1) { //toneGenerator.startTone(ToneGenerator.TONE_DTMF_1, 300); //connection.sendDigits("1"); } else if (v.getId() == R.id.imageButton_2) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_2, 300); connection.sendDigits("2"); } else if (v.getId() == R.id.imageButton_3) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_3, 300); connection.sendDigits("3"); } else if (v.getId() == R.id.imageButton_4) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_4, 300); connection.sendDigits("4"); } else if (v.getId() == R.id.imageButton_5) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_5, 300); connection.sendDigits("5"); } else if (v.getId() == R.id.imageButton_6) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_6, 300); connection.sendDigits("6"); } else if (v.getId() == R.id.imageButton_7) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_7, 300); connection.sendDigits("7"); } else if (v.getId() == R.id.imageButton_8) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_8, 300); connection.sendDigits("8"); } else if (v.getId() == R.id.imageButton_9) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_9, 300); connection.sendDigits("9"); } else if (v.getId() == R.id.imageButton_0) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_0, 300); connection.sendDigits("0"); } else if (v.getId() == R.id.imageButton_star) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_S, 300); connection.sendDigits("*"); } else if (v.getId() == R.id.imageButton_hash) { toneGenerator.startTone(ToneGenerator.TONE_DTMF_P, 300); connection.sendDigits("#"); } else if (v.getId() == R.id.button_cancel) { mListener.onFragmentInteraction("cancel"); } } */ /** * This interface must be implemented by activities that contain this * fragment to allow an interaction in this fragment to be communicated * to the activity and potentially other fragments contained in that * activity. * <p/> * See the Android Training lesson <a href= * "http://developer.android.com/training/basics/fragments/communicating.html" * >Communicating with Other Fragments</a> for more information. */ public interface OnFragmentInteractionListener { // TODO: Update argument type and name void onFragmentInteraction(String action); } public void setConnection(RCConnection connection) { this.connection = connection; } // Bluring didn't work 100% so let's keep it commented out in case we revisit in the future. // Note that this needs minSdkVersion 17 /* private Bitmap getScreenShot(View view) { //View screenView = view.getRootView(); View screenView = view; screenView.setDrawingCacheEnabled(true); //screenView.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache()); screenView.setDrawingCacheEnabled(false); return bitmap; } private Bitmap blurBitmap(Bitmap bitmap) { //Let's create an empty bitmap with the same size of the bitmap we want to blur Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); //Instantiate a new Renderscript RenderScript rs = RenderScript.create(getActivity().getApplicationContext()); //Create an Intrinsic Blur Script using the Renderscript ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); //Create the in/out Allocations with the Renderscript and the in/out bitmaps Allocation allIn = Allocation.createFromBitmap(rs, bitmap); Allocation allOut = Allocation.createFromBitmap(rs, outBitmap); //Set the radius of the blur blurScript.setRadius(25.f); //Perform the Renderscript blurScript.setInput(allIn); blurScript.forEach(allOut); //Copy the final bitmap created by the out Allocation to the outBitmap allOut.copyTo(outBitmap); //recycle the original bitmap bitmap.recycle(); //After finishing everything, we destroy the Renderscript. rs.destroy(); return outBitmap; } */ }