package org.droidplanner.android.activities.helpers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.droidplanner.android.R;
import org.droidplanner.android.DroidPlannerApp;
import org.droidplanner.android.utils.prefs.DroidPlannerPrefs;
import android.app.ActionBar;
import android.app.Activity;
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.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* This is used to show the user a list of bluetooth devices to connect to.
* @author Fredia Huya-Kouadio
*/
public class BluetoothDevicesActivity extends ActionBarActivity {
/**
* This tag is used for logging.
*/
private static final String TAG = BluetoothDevicesActivity.class.getSimpleName();
/**
* Request code used in onActivityResult to check for bluetooth activation
* result.
*/
private static final int REQUEST_ENABLE_BT = 111;
private static final String KEY_DISCOVERED_BT_DEVICES = "key_discovered_bt_devices";
private static final String KEY_IS_DISCOVERY_ON = "key_is_discovery_on";
/**
* Sets to true is discovery is running.
*/
private boolean mIsDiscoveryOn;
/**
* List used to temporary store newly discovered bluetooth devices during discovery.
*/
private ArrayList<BluetoothDevice> mTempNewDevices;
/**
* Bluetooth adapter.
*/
private BluetoothAdapter mBtAdapter;
/**
* Contains the list of bluetooth devices.
*/
private BluetoothDeviceAdapter mBluetoothDevicesAdapter;
/**
* Title for this dialog.
*/
private TextView mDeviceListTitle;
/**
* Progress for this dialog, indicating the device is scanning for new
* bluetooth connections.
*/
private ProgressBar mDeviceListProgressBar;
/**
* Image button used to refresh the list of bluetooth devices.
*/
private ImageButton mRefreshDeviceList;
/**
* The broadcast receiver listens for discovered devices, and changes the
* title when discovery is finished
*/
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, because it's been listed
// already
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
mTempNewDevices.add(device);
mBluetoothDevicesAdapter.setNewDevices(mTempNewDevices);
}
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
// When discovery is finished, change the dialog title, and hide
// the progress bar.
mDeviceListTitle.setText(R.string.select_device);
mDeviceListProgressBar.setVisibility(View.INVISIBLE);
mRefreshDeviceList.setVisibility(View.VISIBLE);
mIsDiscoveryOn = false;
}
}
};
/**
* The on-click listener for all devices in the listviews.
*/
private final AdapterView.OnItemClickListener mDeviceClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Cancel discovery because it's costly, and we're about to connect
mBtAdapter.cancelDiscovery();
// Retrieve the selected bluetooth device
final BluetoothDevice device = (BluetoothDevice) parent.getItemAtPosition(position);
// Stores the mac address in the shared preferences,
// so the bluetooth client can retrieve it on connection.
final Context context = getApplicationContext();
DroidPlannerPrefs mAppPrefs = new DroidPlannerPrefs(context);
mAppPrefs.setBluetoothDeviceName(device.getName());
mAppPrefs.setBluetoothDeviceAddress(device.getAddress());
// Toggle the drone connection
DroidPlannerApp.connectToDrone(context);
// Finish the activity
finish();
}
};
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_ENABLE_BT:
if (resultCode == Activity.RESULT_CANCELED) {
// Bluetooth activation was denied by the user. Dismiss this activity.
finish();
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth_device_list);
// Get the local bluetooth adapter
mBtAdapter = BluetoothAdapter.getDefaultAdapter();
mDeviceListTitle = (TextView) findViewById(R.id.bt_device_list_title);
mDeviceListProgressBar = (ProgressBar) findViewById(R.id.bt_scan_progress_bar);
// Initialize the button to perform device discovery
mRefreshDeviceList = (ImageButton) findViewById(R.id.bt_scan_button);
mRefreshDeviceList.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
doDiscovery();
v.setVisibility(View.INVISIBLE);
}
});
// Initialize array adapters. One for already paired devices,
// and one for newly discovered devices
final Context context = getApplicationContext();
mBluetoothDevicesAdapter = new BluetoothDeviceAdapter(context);
ListView btDevicesListView = (ListView) findViewById(R.id.bt_devices_list);
btDevicesListView.setAdapter(mBluetoothDevicesAdapter);
btDevicesListView.setOnItemClickListener(mDeviceClickListener);
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
if(savedInstanceState != null){
mTempNewDevices = savedInstanceState.getParcelableArrayList(KEY_DISCOVERED_BT_DEVICES);
mIsDiscoveryOn = savedInstanceState.getBoolean(KEY_IS_DISCOVERY_ON);
}
if(mTempNewDevices == null){
mTempNewDevices = new ArrayList<BluetoothDevice>();
}
}
@Override
public void onResume() {
super.onResume();
if (mBtAdapter != null && mBtAdapter.isEnabled()) {
// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
// If there are paired devices, add each one to the ArrayAdapter
mBluetoothDevicesAdapter.setPairedDevices(pairedDevices);
if(!mTempNewDevices.isEmpty()){
mBluetoothDevicesAdapter.setNewDevices(mTempNewDevices);
}
if(mIsDiscoveryOn){
doDiscovery();
}
} else {
// Request that bluetooth be enabled
startActivityForResult(new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE_BT);
}
}
@Override
public void onDestroy() {
super.onDestroy();
// Make sure we're not doing discovery anymore
if (mBtAdapter != null) {
mBtAdapter.cancelDiscovery();
}
unregisterReceiver(mReceiver);
}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
//Store the current list of newly discovered bluetooth devices.
outState.putParcelableArrayList(KEY_DISCOVERED_BT_DEVICES, mTempNewDevices);
//Store if we're currently doing discovery
outState.putBoolean(KEY_IS_DISCOVERY_ON, mIsDiscoveryOn);
}
/**
* Start device discovery with the bluetooth adapter
*/
private void doDiscovery() {
// Indicate scanning in the title
mRefreshDeviceList.setVisibility(View.INVISIBLE);
mDeviceListProgressBar.setVisibility(View.VISIBLE);
mDeviceListTitle.setText(R.string.scanning);
// If we're already discovering, stop it
if (mBtAdapter.isDiscovering())
mBtAdapter.cancelDiscovery();
//Empty the temporary newly discovered list
mTempNewDevices.clear();
// Request discovery from the bluetooth adapter
mIsDiscoveryOn = mBtAdapter.startDiscovery();
}
public static class BluetoothDeviceAdapter extends ArrayAdapter<Object> {
private final LayoutInflater mInflater;
private final List<Object> mPairedDevices = new ArrayList<Object>();
private final List<Object> mNewDevices = new ArrayList<Object>();
public BluetoothDeviceAdapter(Context context) {
super(context, 0);
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setPairedDevices(Collection<BluetoothDevice> pairedDevices){
mPairedDevices.clear();
if(pairedDevices.isEmpty()) {
mPairedDevices.add(getContext().getString(R.string.none_paired));
}
else{
//Add the title first.
mPairedDevices.add(getContext().getString(R.string.title_paired_devices));
mPairedDevices.addAll(pairedDevices);
}
notifyDataSetChanged();
}
public void setNewDevices(List<BluetoothDevice> newDevices){
mNewDevices.clear();
if(newDevices.isEmpty()) {
mNewDevices.add(getContext().getString(R.string.none_found));
}
else{
//Add the title first.
mNewDevices.add(getContext().getString(R.string.title_other_devices));
mNewDevices.addAll(newDevices);
}
notifyDataSetChanged();
}
@Override
public int getCount(){
return mPairedDevices.size() + mNewDevices.size();
}
@Override
public Object getItem(int position){
final int pairedDevicesCount = mPairedDevices.size();
if(position < pairedDevicesCount){
return mPairedDevices.get(position);
}
position = position - pairedDevicesCount;
return mNewDevices.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view;
Object item = getItem(position);
if(item instanceof String){
if (convertView != null && convertView.getId() == R.id.title_bluetooth_devices) {
view = (TextView) convertView;
} else {
view = (TextView) mInflater.inflate(R.layout.list_device_title, parent, false);
}
view.setText(item.toString());
}
else{
if (convertView != null && convertView.getId() == R.id.bluetooth_device_info) {
view = (TextView) convertView;
} else {
view = (TextView) mInflater.inflate(R.layout.list_device_name, parent, false);
}
BluetoothDevice btDevice = (BluetoothDevice) item;
view.setText(btDevice.getName() + "\n" + btDevice.getAddress());
}
return view;
}
}
}