package com.michaelfotiadis.eventtriggeredskypecaller.activities; import java.util.ArrayList; import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice; import uk.co.alt236.bluetoothlelib.device.IBeaconDevice; import uk.co.alt236.bluetoothlelib.util.IBeaconUtils; import uk.co.alt236.bluetoothlelib.util.IBeaconUtils.IBeaconDistanceDescriptor; import android.app.ActionBar; import android.app.PendingIntent; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; import android.os.Bundle; import android.os.Parcelable; import android.os.Vibrator; import android.support.v4.app.DialogFragment; import android.support.v4.content.LocalBroadcastManager; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.ProgressBar; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ToggleButton; import com.github.johnpersano.supertoasts.SuperActivityToast; import com.github.johnpersano.supertoasts.SuperCardToast; import com.michaelfotiadis.eventtriggeredskypecaller.R; import com.michaelfotiadis.eventtriggeredskypecaller.containers.CustomConstants; import com.michaelfotiadis.eventtriggeredskypecaller.containers.DeviceType; import com.michaelfotiadis.eventtriggeredskypecaller.containers.EventContact; import com.michaelfotiadis.eventtriggeredskypecaller.containers.SkypeAction; import com.michaelfotiadis.eventtriggeredskypecaller.dialogs.InterfaceDialogListener; import com.michaelfotiadis.eventtriggeredskypecaller.dialogs.SkypeActionDialogFragment; import com.michaelfotiadis.eventtriggeredskypecaller.utils.BluetoothLeScanner; import com.michaelfotiadis.eventtriggeredskypecaller.utils.BluetoothUtils; import com.michaelfotiadis.eventtriggeredskypecaller.utils.DataUtils; import com.michaelfotiadis.eventtriggeredskypecaller.utils.FileUtils; import com.michaelfotiadis.eventtriggeredskypecaller.utils.Logger; import com.michaelfotiadis.eventtriggeredskypecaller.utils.SkypeUtils; import com.michaelfotiadis.eventtriggeredskypecaller.utils.ToastUtils; public class MainActivity extends SensorBaseActivity implements InterfaceDialogListener { public class ResponseReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Logger.d(TAG, "On Receiver Result"); if (intent.getAction().equalsIgnoreCase( CustomConstants.Broadcasts.BROADCAST_1.getString())) { Logger.i(TAG, "Scan Timed Out"); } } } // Define Tags private final String TAG = "Main Activity"; private final String TAG_ACTION_PICKER = "Skype Action Picker"; // Activity Toast private SuperActivityToast mSuperActivityToast; // Instances of non-static classes private SkypeUtils mSkypeUtilities; private FileUtils mFileUtils; private BluetoothUtils mBluetoothUtils; private String mSkypeUserName; // Toast Strings private final String mToastString1 = "Checking for Skype Installation"; private final String mToastString2 = "Loading Data from Config File"; private final String mToastString3 = "Configuration not found! Please execute setup first."; private final String mToastString4 = "Application Started"; // Data private ArrayList<EventContact> mContactList = new ArrayList<EventContact>(); // Receivers private ResponseReceiver mReceiver; // Widgets private ProgressBar mNfcProgressBar; private ProgressBar mIBeaconProgressBar; private ToggleButton mNfcToggleButton; private SeekBar mSeekBar; private ToggleButton mIBeaconToggleButton; // NDEF Fields private NfcAdapter mNfcAdapter; private IntentFilter[] mNdefExchangeFilters; private PendingIntent mNfcPendingIntent; // BlueTooth Fields private BluetoothLeScanner mScanner; private final int TARGET_SCAN_DURATION = -1; private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { final BluetoothLeDevice deviceLe = new BluetoothLeDevice(device, rssi, scanRecord, System.currentTimeMillis()); runOnUiThread(new Runnable() { @Override public void run() { if (IBeaconUtils.isThisAnIBeacon(deviceLe)) { IBeaconDevice device = new IBeaconDevice(deviceLe); // Get the distance descriptor as an integer int distanceDescriptorValue = new DataUtils() .getValueOfEnum(device.getDistanceDescriptor()); // Compare this integer to the progress bar sensitivity if (distanceDescriptorValue <= mSeekBar.getProgress()) { String result = deviceLe.getAddress(); for (EventContact contact : getContactList()) { if (contact.getDeviceID().equals(result)) { processScanResult(contact, DeviceType.IBEACON); break; } } Logger.i(TAG, "Found an iBeacon"); } } } }); } }; private final int THREAD_SLEEP_TIME = 2000; protected void checkForConfigFile() { mSuperActivityToast = ToastUtils.makeProgressToast(this, mSuperActivityToast, mToastString2); mFileUtils = new FileUtils(); // This is here for debugging // boolean isFileDeleted = mFileUtils.deleteConfigFile(); // Logger.d(TAG, "Did I delete Config File? " + isFileDeleted); if (!mFileUtils.isConfigFileSet(this)) { Logger.d(TAG, "Config File not Found!"); startSetupActivity(true); } else { Logger.d(TAG, "Attempting to Read File"); mFileUtils.readFromConfigFile(this); ToastUtils.dismissToast(mSuperActivityToast); setContactList(new FileUtils().generateContactListFromConfig(this)); for (EventContact contact : getContactList()) { Logger.i(TAG, contact.toString()); } } } /** * Method which checks for Skype installation on the local device and * prompts to open the market if none is present */ protected void checkForSkypeInstallation() { mSuperActivityToast = ToastUtils.makeProgressToast(this, mSuperActivityToast, mToastString1); mSkypeUtilities = new SkypeUtils(); Logger.d(TAG, "Checking for Skype Installation"); // Make sure the Skype for Android client is installed if (!mSkypeUtilities.isSkypeClientInstalled(this)) { ToastUtils.dismissToast(mSuperActivityToast); Logger.i(TAG, "Skype Client Not Found. Going to Market."); ToastUtils.makeInfoToast(this, "Skype Client Not Found. Going to Market."); mSkypeUtilities.goToMarket(this); return; } else { ToastUtils.dismissToast(mSuperActivityToast); Logger.i(TAG, "Skype Installation Detected"); return; } } protected void disableBluetoothScan() { if (mScanner != null) { mScanner.scanLeDevice(-1, false); } } public void disableNFCForegroundMode() { Logger.d(TAG, "disableForegroundMode"); mNfcAdapter.disableForegroundDispatch(this); } public void enableBluetoothScan() { Logger.i(TAG, "Registering the Broadcast Receiver"); IntentFilter mIntentFilter = new IntentFilter( CustomConstants.Broadcasts.BROADCAST_1.getString()); mReceiver = new ResponseReceiver(); Logger.d(TAG, "Registering Receiver"); LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, mIntentFilter); mBluetoothUtils = new BluetoothUtils(this); mScanner = new BluetoothLeScanner(this, mLeScanCallback, mBluetoothUtils); if (!mBluetoothUtils.isBluetoothLeSupported()) { ToastUtils.makeWarningToast(this, "BlueTooth LE is not supported by your device"); return; } runOnUiThread(new Runnable() { @Override public void run() { mBluetoothUtils.askUserToEnableBluetoothIfNeeded(); if (mBluetoothUtils.isBluetoothOn() && mBluetoothUtils.isBluetoothLeSupported()) { Logger.i(TAG, "Starting Scan"); mScanner.scanLeDevice(TARGET_SCAN_DURATION, true); } else { mIBeaconToggleButton.performClick(); } } }); } public void enableNFCForegroundMode() { Logger.d(TAG, "enableForegroundMode"); // Activate the NFC Adapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // make sure that NFC can be detected checkForNFCAdapter(); // Create the Intent mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); // foreground mode gives the current active application priority for // reading scanned tags mNdefExchangeFilters = new IntentFilter[] { new IntentFilter( NfcAdapter.ACTION_TAG_DISCOVERED) }; mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mNdefExchangeFilters, null); } public ArrayList<EventContact> getContactList() { return mContactList; } @Override public void onClickCall(android.support.v4.app.DialogFragment dialog) { ToastUtils.makeInfoToast(MainActivity.this, "Starting Skype"); new SkypeUtils().startSkypeAction(this, mSkypeUserName, SkypeAction.CALL.getString()); } @Override public void onClickChat(android.support.v4.app.DialogFragment dialog) { ToastUtils.makeInfoToast(MainActivity.this, "Starting Skype"); new SkypeUtils().startSkypeAction(this, mSkypeUserName, SkypeAction.CHAT.getString()); } @Override public void onClickIBeacon(DialogFragment dialog) { // Do Nothing } @Override public void onClickNFC(DialogFragment dialog) { // Do Nothing } /** * OnClick handler which starts the Register Contact Activity * * @param view */ public void onClickRegisterContact(View view) { startSetupActivity(false); } public void onClickToggleIBeacon(View view) { // Is the toggle on? boolean on = ((ToggleButton) view).isChecked(); if (on) { mIBeaconProgressBar.setVisibility(View.VISIBLE); enableBluetoothScan(); } else { Logger.d(TAG, "Stopping Scan"); disableBluetoothScan(); mIBeaconProgressBar.setVisibility(View.INVISIBLE); } } public void onClickToggleNFC(View view) { // Is the toggle on? boolean on = ((ToggleButton) view).isChecked(); if (on) { mNfcProgressBar.setVisibility(View.VISIBLE); Logger.d(TAG, "Giving NFC Priority to this App"); // Initialise NFC enableNFCForegroundMode(); } else { mNfcProgressBar.setVisibility(View.INVISIBLE); // Disable NFC disableNFCForegroundMode(); Logger.d(TAG, "Disabling NFC"); } } @Override public void onClickVideoCall(android.support.v4.app.DialogFragment dialog) { ToastUtils.makeInfoToast(MainActivity.this, "Starting Skype"); new SkypeUtils().startSkypeAction(this, mSkypeUserName, SkypeAction.VIDEO_CALL.getString()); } @Override protected void onCreate(Bundle savedInstanceState) { Logger.i(TAG, "Starting Main Activity"); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // gets the activity's default ActionBar ActionBar actionBar = getActionBar(); actionBar.show(); // Activate the NFC Adapter mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // Set Widgets mNfcProgressBar = (ProgressBar) findViewById(R.id.progressBarNFC); mIBeaconProgressBar = (ProgressBar) findViewById(R.id.progressBarIBeacon); mNfcToggleButton = (ToggleButton) findViewById(R.id.toggleButtonNFC); mIBeaconToggleButton = (ToggleButton) findViewById(R.id.toggleButtonIBeacon); mSeekBar = (SeekBar) findViewById(R.id.seekBarSensitivity); setupSeekBar(); // Look for Skype Installation checkForSkypeInstallation(); // Look for Local File checkForConfigFile(); mSuperActivityToast = ToastUtils.makeInfoToast(this, mToastString4); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.activity_setup_actions, menu); return super.onCreateOptionsMenu(menu); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { Logger.d(TAG, "Detected New NFC Intent"); vibrate(); NdefMessage[] messages = null; Parcelable[] rawMsgs = intent .getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMsgs != null) { messages = new NdefMessage[rawMsgs.length]; for (int i = 0; i < rawMsgs.length; i++) { messages[i] = (NdefMessage) rawMsgs[i]; } } if (messages[0] != null) { String result = ""; byte[] payload = messages[0].getRecords()[0].getPayload(); // this assumes that we get back am SOH followed by host/code for (int b = 1; b < payload.length; b++) { // skip SOH result += (char) payload[b]; } for (EventContact contact : getContactList()) { if (contact.getDeviceID().equals(result)) { processScanResult(contact, DeviceType.NFC); break; } } } } } @Override public boolean onOptionsItemSelected(MenuItem item) { // same as using a normal menu switch (item.getItemId()) { case R.id.item_list: mSuperActivityToast = ToastUtils.makeInfoToast(this, "Displaying List"); // Display the configuration data in a new activity startListDisplayActivity(); break; } return true; } /** * Called when activity gets invisible */ @Override protected void onPause() { super.onPause(); // Cancel all toasts currently showing SuperActivityToast.cancelAllSuperActivityToasts(); disableBluetoothScan(); removeReceivers(); } @Override protected void onResume() { super.onResume(); checkForConfigFile(); // Cancel all toasts currently showing SuperActivityToast.cancelAllSuperActivityToasts(); if (mNfcToggleButton.isChecked()) { enableNFCForegroundMode(); } if (mIBeaconToggleButton.isChecked()) { enableBluetoothScan(); } } public void onStart() { super.onStart(); setContactList(new FileUtils().generateContactListFromConfig(this)); } public void processScanResult(EventContact contact, DeviceType deviceType) { if (deviceType == DeviceType.IBEACON) { mIBeaconToggleButton.performClick(); } Logger.d(TAG, "Device ID matches contact " + contact.getContactName()); Logger.d(TAG, "Action is "+ contact.getContactAction()); mSkypeUserName = contact.getContactName(); // Start the progress dialog showSkypeInitProgressDialog(deviceType, contact.getContactName(), contact.getContactAction()); } protected void removeReceivers() { try { LocalBroadcastManager.getInstance(this).unregisterReceiver( mReceiver); Logger.d(TAG, "Receiver Unregistered Successfully"); } catch (Exception e) { Logger.d( TAG, "Receiver Already Unregistered. Exception : " + e.getLocalizedMessage()); } } public void setContactList(ArrayList<EventContact> contactList) { this.mContactList = contactList; } /** * Seek Bar which allows user to setup BlueTooth scanning sensitivity */ protected void setupSeekBar() { mSeekBar.setProgress(0); mSeekBar.incrementProgressBy(1); mSeekBar.setMax(2); mSeekBar.setProgress(1); final TextView mSeekBarValue = (TextView) findViewById(R.id.textViewBlueToothSensitivity); mSeekBarValue.setText(this.getString( R.string.label_bluetooth_sensitivity) + CustomConstants.LINE_SEPARATOR + String.valueOf(IBeaconDistanceDescriptor.NEAR)); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar mSeekBar, int progress, boolean fromUser) { IBeaconDistanceDescriptor descriptor = new DataUtils() .getEnumOfValue(progress); mSeekBarValue.setText(MainActivity.this.getString( R.string.label_bluetooth_sensitivity) + CustomConstants.LINE_SEPARATOR + String.valueOf(descriptor.toString())); } @Override public void onStartTrackingTouch(SeekBar mSeekBar) { } @Override public void onStopTrackingTouch(SeekBar mSeekBar) { } }); } private void showSkypeInitProgressDialog(DeviceType deviceType, final String skypeUserName, final String action) { // Cancel all SuperCardToasts already showing SuperCardToast.cancelAllSuperCardToasts(); // Create a progress dialogue final ProgressDialog progressDialogue = ProgressDialog.show(MainActivity.this, "Found: " + deviceType, "User: " + skypeUserName + CustomConstants.LINE_SEPARATOR + "Action: " + action); // start a new thread to process job Thread t = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(THREAD_SLEEP_TIME); if (action.equals(SkypeAction.PROMPT_USER .getString())) { Logger.d(TAG, "Prompting User"); new SkypeActionDialogFragment().show(getSupportFragmentManager(), TAG_ACTION_PICKER); } else { ToastUtils.makeInfoToast(MainActivity.this, "Starting Skype"); mSkypeUtilities.startSkypeAction(MainActivity.this, skypeUserName, action); } progressDialogue.cancel(); } catch (InterruptedException e) { progressDialogue.cancel(); Logger.e(TAG, e.getLocalizedMessage()); } } }); t.start(); } @SuppressWarnings("unchecked") private void startListDisplayActivity() { if (mContactList != null && mContactList.size() > 0) { Intent intent = new Intent(this, ListDisplayActivity.class); intent.putParcelableArrayListExtra(CustomConstants.EXTRA_PAYLOAD, (ArrayList<? extends Parcelable>) getContactList()); startActivity(intent); } else { mSuperActivityToast = ToastUtils.makeWarningToast(this, mToastString3); } } @SuppressWarnings("unchecked") private void startSetupActivity(boolean firstTimeSetup) { Logger.i(TAG, "Starting First Time Setup"); Intent intent = new Intent(this, SetupActivity.class); intent.putParcelableArrayListExtra(CustomConstants.EXTRA_PAYLOAD, (ArrayList<? extends Parcelable>) getContactList()); startActivity(intent); if (firstTimeSetup) { // Do not return here if the configuration file is not set yet finish(); } } private void vibrate() { Logger.d(TAG, "vibrate"); Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); vibe.vibrate(500); } }