2 * SaveMySugar - Exchange messages using the distance between phone calls
4 * Copyright (C) 2015 Antonio Ospite <ao2@ao2.it>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * adouble with this program. If not, see <http://www.gnu.org/licenses/>.
20 package it.ao2.savemysugar;
22 import android.content.Context;
23 import android.os.Bundle;
24 import android.support.v4.app.Fragment;
25 import android.telephony.PhoneStateListener;
26 import android.telephony.TelephonyManager;
27 import android.text.method.ScrollingMovementMethod;
28 import android.view.LayoutInflater;
29 import android.view.View;
30 import android.view.ViewGroup;
31 import android.widget.TextView;
32 import android.widget.Toast;
34 import java.util.Locale;
36 import it.ao2.savemysugar.util.TimeLog;
37 import it.ao2.util.morse.MorseDistanceModulator;
38 import it.ao2.util.morse.MorseTranslator;
40 public class ReceiveFragment extends Fragment {
42 private static final String TAG = "SaveMySugar";
43 private TextView mLogWindow;
44 private MorseDistanceModulator mModulator;
45 private MorseTranslator mTranslator;
46 private SaveMySugarPhoneStateListener mListener;
48 private class SaveMySugarPhoneStateListener extends PhoneStateListener {
50 private double mPreviousRingTime = -1;
51 private double mPreviousCallTime = -1;
52 private String mMorseMessage = "";
54 public void onCallStateChanged(int state, String incomingNumber) {
56 case TelephonyManager.CALL_STATE_IDLE:
57 TimeLog.log(TAG, mLogWindow, "CALL_STATE_IDLE\n");
59 case TelephonyManager.CALL_STATE_OFFHOOK:
60 TimeLog.log(TAG, mLogWindow, "CALL_STATE_OFFHOOK\n");
62 case TelephonyManager.CALL_STATE_RINGING:
63 TimeLog.log(TAG, mLogWindow, "CALL_STATE_RINGING " + incomingNumber + "\n");
64 double currentRingTime = System.currentTimeMillis() / 1000.;
66 if (mPreviousRingTime == -1) {
67 mPreviousRingTime = currentRingTime;
68 mPreviousCallTime = currentRingTime;
69 TimeLog.log(TAG, mLogWindow, "call distance 0 Received \"\" (The very first ring)\n");
73 double ringDistance = currentRingTime - mPreviousRingTime;
74 TimeLog.log(TAG, mLogWindow, "RINGs distance " + String.format(Locale.US, "%.2f", ringDistance) + "\n");
75 mPreviousRingTime = currentRingTime;
77 // Ignore multiple rings in the same call
78 if (mModulator.isSamePeriod(ringDistance)) {
79 TimeLog.log(TAG, mLogWindow, "Multiple rings in the same call, distance: "
80 + String.format(Locale.US, "%.2f", ringDistance) + "\n");
84 double callDistance = currentRingTime - mPreviousCallTime;
85 mPreviousCallTime = currentRingTime;
88 String symbol = mModulator.distanceToSymbol(callDistance);
90 String extraInfo = "";
91 // When a separator is met, log the last Morse signal
92 if (symbol.equals(" ") || symbol.equals("/") || symbol.equals("EOM")) {
93 String[] signals = mMorseMessage.split(" ");
94 String lastSignal = signals[signals.length - 1];
95 Character lastCharacter = mTranslator.signalToCharacter(lastSignal);
96 extraInfo = " got \"" + lastCharacter + "\"";
99 TimeLog.log(TAG, mLogWindow, "call distance " + String.format(Locale.US, "%.2f", callDistance)
100 + " Received \"" + symbol + "\"" + extraInfo + "\n");
102 if (symbol.equals("EOM")) {
103 String text = mTranslator.morseToText(mMorseMessage);
104 TimeLog.log(TAG, mLogWindow, "Message received: " + text + "\n");
107 // Add spaces around the wordspace symbol to make it
108 // easier to split the Morse message later on
109 if (symbol.equals("/")) {
112 mMorseMessage += symbol;
114 } catch (IllegalArgumentException e) {
115 Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
121 super.onCallStateChanged(state, incomingNumber);
126 public void onAttach(Context context) {
127 super.onAttach(context);
128 mModulator = ((SaveMySugarApplication) getActivity().getApplication()).getModulator();
129 mTranslator = ((SaveMySugarApplication) getActivity().getApplication()).getTranslator();
131 if (mListener == null) {
132 mListener = new SaveMySugarPhoneStateListener();
134 TelephonyManager telephonyMgr = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
135 telephonyMgr.listen(mListener, PhoneStateListener.LISTEN_CALL_STATE);
137 // If we used a Service this would not be necessary
138 setRetainInstance(true);
143 public View onCreateView(LayoutInflater inflater, ViewGroup container,
144 Bundle savedInstanceState) {
145 View view = inflater.inflate(R.layout.fragment_receive, container, false);
147 mLogWindow = (TextView) view.findViewById(R.id.receive_log_window);
148 mLogWindow.setMovementMethod(new ScrollingMovementMethod());