/* * SaveMySugar - Exchange messages using the distance between phone calls * * Copyright (C) 2015 Antonio Ospite * * 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * adouble with this program. If not, see . */ package it.ao2.savemysugar; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.text.method.ScrollingMovementMethod; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; import java.util.Locale; import it.ao2.savemysugar.util.TimeLog; import it.ao2.util.morse.MorseDistanceModulator; import it.ao2.util.morse.MorseTranslator; public class ReceiveFragment extends Fragment { private static final String TAG = "SaveMySugar"; private TextView mLogWindow; private MorseDistanceModulator mModulator; private MorseTranslator mTranslator; private SaveMySugarPhoneStateListener mListener; private class SaveMySugarPhoneStateListener extends PhoneStateListener { private double mPreviousRingTime = -1; private double mPreviousCallTime = -1; private String mMorseMessage = ""; public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_IDLE: TimeLog.log(TAG, mLogWindow, "CALL_STATE_IDLE\n"); break; case TelephonyManager.CALL_STATE_OFFHOOK: TimeLog.log(TAG, mLogWindow, "CALL_STATE_OFFHOOK\n"); break; case TelephonyManager.CALL_STATE_RINGING: TimeLog.log(TAG, mLogWindow, "CALL_STATE_RINGING " + incomingNumber + "\n"); double currentRingTime = System.currentTimeMillis() / 1000.; if (mPreviousRingTime == -1) { mPreviousRingTime = currentRingTime; mPreviousCallTime = currentRingTime; TimeLog.log(TAG, mLogWindow, "call distance 0 Received \"\" (The very first ring)\n"); break; } double ringDistance = currentRingTime - mPreviousRingTime; TimeLog.log(TAG, mLogWindow, "RINGs distance " + String.format(Locale.US, "%.2f", ringDistance) + "\n"); mPreviousRingTime = currentRingTime; // Ignore multiple rings in the same call if (mModulator.isSamePeriod(ringDistance)) { TimeLog.log(TAG, mLogWindow, "Multiple rings in the same call, distance: " + String.format(Locale.US, "%.2f", ringDistance) + "\n"); break; } double callDistance = currentRingTime - mPreviousCallTime; mPreviousCallTime = currentRingTime; try { String symbol = mModulator.distanceToSymbol(callDistance); String extraInfo = ""; // When a separator is met, log the last Morse signal if (symbol.equals(" ") || symbol.equals("/") || symbol.equals("EOM")) { String[] signals = mMorseMessage.split(" "); String lastSignal = signals[signals.length - 1]; Character lastCharacter = mTranslator.signalToCharacter(lastSignal); extraInfo = " got \"" + lastCharacter + "\""; } TimeLog.log(TAG, mLogWindow, "call distance " + String.format(Locale.US, "%.2f", callDistance) + " Received \"" + symbol + "\"" + extraInfo + "\n"); if (symbol.equals("EOM")) { String text = mTranslator.morseToText(mMorseMessage); TimeLog.log(TAG, mLogWindow, "Message received: " + text + "\n"); mMorseMessage = ""; } else { // Add spaces around the wordspace symbol to make it // easier to split the Morse message later on if (symbol.equals("/")) { symbol = " / "; } mMorseMessage += symbol; } } catch (IllegalArgumentException e) { Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show(); } break; default: break; } super.onCallStateChanged(state, incomingNumber); } }; @Override public void onAttach(Context context) { super.onAttach(context); mModulator = ((SaveMySugarApplication) getActivity().getApplication()).getModulator(); mTranslator = ((SaveMySugarApplication) getActivity().getApplication()).getTranslator(); if (mListener == null) { mListener = new SaveMySugarPhoneStateListener(); TelephonyManager telephonyMgr = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE); telephonyMgr.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE); // If we used a Service this would not be necessary setRetainInstance(true); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_receive, container, false); mLogWindow = (TextView) view.findViewById(R.id.receive_log_window); mLogWindow.setMovementMethod(new ScrollingMovementMethod()); return view; } }