Prechádzať zdrojové kódy

Initial commit for Bluetooth related projects.

Cristian Tanas 11 rokov pred
rodič
commit
aef3d4a197
36 zmenil súbory, kde vykonal 1173 pridanie a 0 odobranie
  1. 33 0
      BluetoothConnect/AndroidManifest.xml
  2. BIN
      BluetoothConnect/ic_launcher-web.png
  3. BIN
      BluetoothConnect/libs/android-support-v4.jar
  4. BIN
      BluetoothConnect/res/drawable-hdpi/ic_launcher.png
  5. BIN
      BluetoothConnect/res/drawable-mdpi/ic_launcher.png
  6. BIN
      BluetoothConnect/res/drawable-xhdpi/ic_launcher.png
  7. BIN
      BluetoothConnect/res/drawable-xxhdpi/ic_launcher.png
  8. 47 0
      BluetoothConnect/res/layout/activity_main.xml
  9. 11 0
      BluetoothConnect/res/layout/list_footerview.xml
  10. 9 0
      BluetoothConnect/res/layout/list_item.xml
  11. 11 0
      BluetoothConnect/res/values-v11/styles.xml
  12. 12 0
      BluetoothConnect/res/values-v14/styles.xml
  13. 16 0
      BluetoothConnect/res/values/strings.xml
  14. 20 0
      BluetoothConnect/res/values/styles.xml
  15. 93 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothAcceptConnectionThread.java
  16. 87 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothConnectThread.java
  17. 87 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothManageConnectionThread.java
  18. 133 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothNeighboursListActivity.java
  19. 16 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/ConnectionInfo.java
  20. 241 0
      BluetoothConnect/src/org/uab/android/bluetooth/connect/MainActivity.java
  21. 33 0
      BluetoothNeighbourDiscovery/AndroidManifest.xml
  22. BIN
      BluetoothNeighbourDiscovery/ic_launcher-web.png
  23. BIN
      BluetoothNeighbourDiscovery/libs/android-support-v4.jar
  24. BIN
      BluetoothNeighbourDiscovery/res/drawable-hdpi/ic_launcher.png
  25. BIN
      BluetoothNeighbourDiscovery/res/drawable-mdpi/ic_launcher.png
  26. BIN
      BluetoothNeighbourDiscovery/res/drawable-xhdpi/ic_launcher.png
  27. BIN
      BluetoothNeighbourDiscovery/res/drawable-xxhdpi/ic_launcher.png
  28. 17 0
      BluetoothNeighbourDiscovery/res/layout/activity_main.xml
  29. 11 0
      BluetoothNeighbourDiscovery/res/layout/list_footerview.xml
  30. 9 0
      BluetoothNeighbourDiscovery/res/layout/list_item.xml
  31. 11 0
      BluetoothNeighbourDiscovery/res/values-v11/styles.xml
  32. 12 0
      BluetoothNeighbourDiscovery/res/values-v14/styles.xml
  33. 9 0
      BluetoothNeighbourDiscovery/res/values/strings.xml
  34. 20 0
      BluetoothNeighbourDiscovery/res/values/styles.xml
  35. 133 0
      BluetoothNeighbourDiscovery/src/org/uab/android/bluetooth/simple/BluetoothNeighboursListActivity.java
  36. 102 0
      BluetoothNeighbourDiscovery/src/org/uab/android/bluetooth/simple/MainActivity.java

+ 33 - 0
BluetoothConnect/AndroidManifest.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.uab.android.bluetooth.connect"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+    
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity 
+            android:name=".BluetoothNeighboursListActivity"
+            android:label="@string/app_name"/>
+    </application>
+
+</manifest>

BIN
BluetoothConnect/ic_launcher-web.png


BIN
BluetoothConnect/libs/android-support-v4.jar


BIN
BluetoothConnect/res/drawable-hdpi/ic_launcher.png


BIN
BluetoothConnect/res/drawable-mdpi/ic_launcher.png


BIN
BluetoothConnect/res/drawable-xhdpi/ic_launcher.png


BIN
BluetoothConnect/res/drawable-xxhdpi/ic_launcher.png


+ 47 - 0
BluetoothConnect/res/layout/activity_main.xml

@@ -0,0 +1,47 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="${relativePackage}.${activityClass}" >
+
+    <Button
+        android:id="@+id/deviceDiscoveryBt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:text="@string/discover"
+        android:enabled="false" />
+
+    <ProgressBar
+        android:id="@+id/progressBar"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentTop="true"
+        android:indeterminate="true"
+        android:visibility="invisible" />
+
+    <TextView
+        android:id="@+id/statusTv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBottom="@+id/progressBar"
+        android:layout_alignParentLeft="true"
+        android:layout_toLeftOf="@+id/progressBar"
+        android:layout_marginLeft="10dp"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <TextView
+        android:id="@+id/bluetoothDataTv"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignLeft="@+id/statusTv"
+        android:layout_alignParentRight="true"
+        android:layout_below="@+id/statusTv"
+        android:layout_marginLeft="15dp"
+        android:layout_marginTop="136dp"
+        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+</RelativeLayout>

+ 11 - 0
BluetoothConnect/res/layout/list_footerview.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/footer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal"
+    android:text="@string/discoverFooterView"
+    android:textSize="20sp" >
+    
+
+</TextView>

+ 9 - 0
BluetoothConnect/res/layout/list_item.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="10dp"
+    android:textSize="24sp" >
+    
+
+</TextView>

+ 11 - 0
BluetoothConnect/res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
BluetoothConnect/res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 16 - 0
BluetoothConnect/res/values/strings.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">BluetoothConnect</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="discover">Device discovery</string>
+    <string name="discoverFooterView">Discover more devices</string>
+    <string name="clientMode">Connected in CLIENT mode.</string>
+    <string name="serverMode">Connected in SERVER mode.</string>
+    <string name="connecting">Connecting to remote Bluetooth device...</string>
+    <string name="connected">Connected to remote Bluetooth device.</string>
+    <string name="bluetoothError">Bluetooth error! See below.</string>
+    <string name="echoMessage">Hello, Bluetooth!</string>
+    <string name="appInfo">To enter SERVER mode press and hold the Device discovery button!</string>
+
+</resources>

+ 20 - 0
BluetoothConnect/res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 93 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothAcceptConnectionThread.java

@@ -0,0 +1,93 @@
+package org.uab.android.bluetooth.connect;
+
+import java.io.IOException;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothSocket;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class BluetoothAcceptConnectionThread extends Thread {
+	
+	// Socket for listening incoming connection requests
+	BluetoothServerSocket 	serverSocket;
+	
+	// Reference to the local Bluetooth adapter
+	BluetoothAdapter		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+	
+	// Handler object to communicate results back to the MainActivity
+	Handler					handler;
+	
+	public BluetoothAcceptConnectionThread(Handler handler) {
+		
+		this.handler = handler;
+		
+		// Get a BluetoothServerSocket
+		try {
+			
+			this.serverSocket = this.bluetoothAdapter
+					.listenUsingRfcommWithServiceRecord(
+							"Bluetooth Demo", 					// An arbitrary name (could be the application name).
+							ConnectionInfo.BLUETOOTH_APP_UUID	// UUID for the Bluetooth service
+							);
+		} catch (IOException e) { 
+			Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+			this.handler.sendMessage(msg);
+		}
+	}
+
+	@Override
+	public void run() {
+		
+		BluetoothSocket clientSocket;
+		
+		// Start listening for connection requests
+		while ( true ) {
+			
+			// This is a blocking call and it only returns when either a connection has been accepted 
+			// or an exception has occurred.
+			try {
+				clientSocket = serverSocket.accept();
+			} catch (IOException e) {
+				break;
+			}
+			
+			// If the connection has been accepted
+			if ( clientSocket != null ) {
+				
+				// Manage the connection in a separate Thread
+				manageConnectedSocket(clientSocket);
+				
+				// Close the BluetoothServerSocket as typically only one connection is allows per RFCOMM channel
+				try {
+					serverSocket.close();
+				} catch (IOException e) {
+					Log.e("BLUETOOTH_CONNECT", e.getMessage());
+				}
+				
+				break;
+			}
+		}
+	}
+	
+	/**
+	 * Initiates a Thread for transferring data.
+	 * 
+	 * @param socket BluetoothSocket for which the connection has been accepted.
+	 */
+	private void manageConnectedSocket(BluetoothSocket socket) {
+		
+		BluetoothManageConnectionThread connectionThread = 
+				new BluetoothManageConnectionThread(
+						socket, 								// Incoming BluetoothSocket
+						this.handler									// Handler object to communicate results back to the main Thread
+						);
+		
+		Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_SOCKET_CONNECTED, connectionThread);
+		this.handler.sendMessage(msg);
+		
+		connectionThread.start();
+	}
+}

+ 87 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothConnectThread.java

@@ -0,0 +1,87 @@
+package org.uab.android.bluetooth.connect;
+
+import java.io.IOException;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+public class BluetoothConnectThread extends Thread {
+	
+	// Bluetooth device to connect to
+	BluetoothDevice		connectToDevice;
+	
+	// Bluetooth socket for the remote bluetooth connection
+	BluetoothSocket		remoteBluetoothSocket;
+	
+	// UI Thread handler to communicate back connection results
+	Handler				handler;
+	
+	public BluetoothConnectThread(BluetoothDevice device, Handler handler) {
+		
+		this.connectToDevice = device;
+		this.handler = handler;
+		
+		// Initialize the BluetoothSocket that will connect to the BluetoothDevice
+		try {
+			this.remoteBluetoothSocket = this.connectToDevice
+					.createRfcommSocketToServiceRecord(
+							ConnectionInfo.BLUETOOTH_APP_UUID	// Service record UUID to search a RFCOMM channel
+							);
+		} catch (IOException e) {
+			
+			Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+			this.handler.sendMessage(msg);
+		}
+	}
+
+	@Override
+	public void run() {
+		
+		// Make sure to stop the neighbour discovery before connecting to a device
+		if ( BluetoothAdapter.getDefaultAdapter().isDiscovering() )
+			BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
+		
+		// Connect to the Bluetooth device
+		try {
+			this.remoteBluetoothSocket.connect();	// This performs an SDP lookup on the remote device in order to match the UUID.
+		} catch (IOException e) {
+			
+			try { 
+				this.remoteBluetoothSocket.close(); 
+			} catch (IOException closeException) {
+				Log.e("BLUETOOTH_CONNECT", closeException.getMessage());
+			}
+			
+			Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+			this.handler.sendMessage(msg);
+		}
+		
+		// Manage the connected socket in a separate Thread
+		manageConnectedSocket(this.remoteBluetoothSocket);
+	}
+	
+	/**
+	 * Initiates a Thread for transferring data.
+	 * 
+	 * @param socket BluetoothSocket for which the connection has been accepted.
+	 */
+	private void manageConnectedSocket(BluetoothSocket socket) {
+		
+		// Send a Message back to MainActivity informing that the socket has been connected 
+		// and pass in a reference to the connection Thread
+		BluetoothManageConnectionThread connectionThread = 
+				new BluetoothManageConnectionThread(
+						socket,
+						this.handler
+						);
+
+		Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_SOCKET_CONNECTED, connectionThread);
+		this.handler.sendMessage(msg);
+
+		connectionThread.start();
+	}
+}

+ 87 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothManageConnectionThread.java

@@ -0,0 +1,87 @@
+package org.uab.android.bluetooth.connect;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import android.bluetooth.BluetoothSocket;
+import android.os.Handler;
+import android.os.Message;
+
+public class BluetoothManageConnectionThread extends Thread {
+
+	// Connected BluetoothSocket
+	BluetoothSocket bluetoothSocket;
+	
+	// Handler object to communicate results back to the main Thread
+	Handler			handler;
+	
+	// Stream objects to handle transmissions through the socket
+	InputStream 	socketInputStream;
+	OutputStream	socketOutputStream;
+	
+	public BluetoothManageConnectionThread(BluetoothSocket socket, Handler handler) {
+		
+		this.bluetoothSocket = socket;
+		this.handler = handler;
+		
+		// Initialize the InputStream and OutputStream to read and write data through the socket
+		try {
+			this.socketInputStream = this.bluetoothSocket.getInputStream();
+			this.socketOutputStream = this.bluetoothSocket.getOutputStream();
+		} catch(IOException e) {
+			
+			Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+			this.handler.sendMessage(msg);
+		}
+	}
+	
+	@Override
+	public void run() {
+		
+		Message msg;
+		
+		// Buffer store for the stream
+		byte[] inputBuffer = new byte[1024];
+		
+		// Bytes read from the stream
+		int bytesRead;
+		
+		// Read from the InputStream. This call will block until there is something to read from the stream.
+		while ( true ) {
+			
+			try {
+				
+				bytesRead = socketInputStream.read(inputBuffer);
+				
+				// Send the obtained data back to the UI Thread
+				String stringData = new String(inputBuffer, 0, bytesRead);
+				msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_DATA_RECEIVED, stringData);
+				this.handler.sendMessage(msg);
+				
+			} catch (IOException e) {
+				
+				msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+				this.handler.sendMessage(msg);
+				break;
+			}
+		}
+	}
+	
+	/**
+	 * Sends data to the remote device.
+	 * 
+	 * @param bytesToWrite Bytes to send to the remote device.
+	 */
+	public void writeToSocket(byte[] bytesToWrite) {
+		
+		try {
+			
+			this.socketOutputStream.write(bytesToWrite);
+			
+		} catch (IOException e) {
+			Message msg = this.handler.obtainMessage(MainActivity.BLUETOOTH_ERROR, e.getMessage());
+			this.handler.sendMessage(msg);
+		}
+	}
+}

+ 133 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/BluetoothNeighboursListActivity.java

@@ -0,0 +1,133 @@
+package org.uab.android.bluetooth.connect;
+
+import java.util.ArrayList;
+
+import android.app.ListActivity;
+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.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class BluetoothNeighboursListActivity extends ListActivity {
+
+	static final String EXTRA_DEVICES = "EXTRA_DEVICES";
+	
+	BluetoothAdapter		bluetoothAdapter;
+	
+	ListView				neighboursListView;
+	ArrayAdapter<String> 	neighboursListAdapter;
+	
+	public static Intent getCallingIntent(Context context, ArrayList<String> devices) {
+		
+		Intent listNeighboursIntent = new Intent(context, BluetoothNeighboursListActivity.class);
+		listNeighboursIntent.putStringArrayListExtra(EXTRA_DEVICES, devices);
+		return listNeighboursIntent;
+	}
+	
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		
+		// Get a reference to the default BluetoothAdapter
+		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+		
+		// Get a reference to the ListView
+		neighboursListView = getListView();
+		
+		// Create a FooterView for the ListView
+		LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+		View footerView = layoutInflater.inflate(R.layout.list_footerview, neighboursListView, false);
+		
+		neighboursListView.setFooterDividersEnabled(true);
+		
+		// Add the FooterView to the list
+		neighboursListView.addFooterView(footerView, null, true);
+		
+		// Get the list of paired devices already discovered
+		ArrayList<String> pairedDevices = getIntent().getStringArrayListExtra(EXTRA_DEVICES);
+		
+		// Initialize the list's ArrayAdapter
+		neighboursListAdapter = new ArrayAdapter<String>(
+				this, 						// Context
+				R.layout.list_item, 		// View for the list items
+				pairedDevices				// Data objects
+				);
+		neighboursListView.setAdapter(neighboursListAdapter);
+		
+		// Set the ListView OnItemClickListener
+		neighboursListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+			@Override
+			public void onItemClick(AdapterView<?> parent, View view, int position,
+					long id) {
+				
+				// If the user clicked on the ListView's footer start discovering neighbours
+				if ( parent.getAdapter().getItemViewType(position) == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER ) {
+					
+					bluetoothAdapter.startDiscovery();
+				}
+				else {
+					
+					// Cancel neighbours discovery
+					bluetoothAdapter.cancelDiscovery();
+					
+					// Get the device's MAC Address
+					String selectedDevice = (String) parent.getItemAtPosition(position);
+					String macAddress = selectedDevice.split("\n")[1];
+					
+					BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(macAddress);
+					
+					// Create an Intent to return the selected bluetooth device to the calling Activity
+					Intent dataIntent = new Intent();
+					dataIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, bluetoothDevice);
+					setResult(RESULT_OK, dataIntent);
+					finish();
+				}
+				
+			}
+		});
+	}
+	
+	@Override
+	protected void onResume() {
+		super.onResume();
+		
+		// Register a BroadcastReceiver for new devices discovery
+		IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+		registerReceiver(neighboursDiscoveryReceiver, discoveryFilter);
+	}
+	
+	@Override
+	protected void onPause() {
+		super.onPause();
+		
+		bluetoothAdapter.cancelDiscovery();
+		unregisterReceiver(neighboursDiscoveryReceiver);
+	}
+	
+	
+	BroadcastReceiver neighboursDiscoveryReceiver = new BroadcastReceiver() {
+		
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			
+			// A new Bluetooth device has been found
+			if ( intent.getAction().equals(BluetoothDevice.ACTION_FOUND) ) {
+				
+				BluetoothDevice device = intent
+						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+				neighboursListAdapter.add(device.getName() + "\n" + device.getAddress());
+				neighboursListAdapter.notifyDataSetChanged();
+			}
+			
+		}
+	};
+}

+ 16 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/ConnectionInfo.java

@@ -0,0 +1,16 @@
+package org.uab.android.bluetooth.connect;
+
+import java.util.UUID;
+
+public class ConnectionInfo {
+
+	// An identifiable name for the Bluetooth service.
+	// When a client attempts to connect with a Bluetooth device, it will 
+	// carry a UUID that uniquely identifies the service with which it wants 
+	// to connect. The UUID from the client must match the stored UUID in the 
+	// server for the connection to be accepted.
+	//
+	// More on UUID: http://en.wikipedia.org/wiki/Universally_unique_identifier
+	public static UUID BLUETOOTH_APP_UUID = 
+			UUID.fromString("66702e86-c33e-4d47-9b55-7f7ea66c704a");
+}

+ 241 - 0
BluetoothConnect/src/org/uab/android/bluetooth/connect/MainActivity.java

@@ -0,0 +1,241 @@
+package org.uab.android.bluetooth.connect;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class MainActivity extends Activity {
+	
+	// Bluetooth Message IDs
+	public static final int BLUETOOTH_ERROR = 500;
+	public static final int BLUETOOTH_SOCKET_CONNECTED = 200;
+	public static final int BLUETOOTH_DATA_RECEIVED = 201;
+
+	// Request codes
+	static final int BLUETOOTH_ENABLE_REQ = 101;
+	static final int BLUETOOTH_CHOOSE_NEIGHBOUR = 102;
+	
+	// Represent the local Bluetooth adapter (Bluetooth radio).
+	// Is the entry-point for all Bluetooth interaction.
+	BluetoothAdapter	bluetoothAdapter;
+	
+	// Determines if the Bluetooth adapter is connected in server or in client mode
+	boolean 			isInServerMode;
+	
+	// Layout Views references
+	ProgressBar			progressBar;
+	
+	TextView			statusTv;
+	TextView			bluetoothDataTv;
+	
+	Button				deviceDiscoveryButton;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+		progressBar = (ProgressBar) findViewById(R.id.progressBar);
+		statusTv = (TextView) findViewById(R.id.statusTv);
+		statusTv.setText(R.string.clientMode);
+		bluetoothDataTv = (TextView) findViewById(R.id.bluetoothDataTv);
+		
+		deviceDiscoveryButton = (Button) findViewById(R.id.deviceDiscoveryBt);
+		
+		// Discover local device's neighbours if users clicks on this Button
+		deviceDiscoveryButton.setOnClickListener(new View.OnClickListener() {
+			
+			@Override
+			public void onClick(View v) {
+				
+				discoverNeighbours();
+			}
+		});
+		
+		// Set the Bluetooth adapter in server mode if the user long-clicks this Button
+		deviceDiscoveryButton.setOnLongClickListener(new View.OnLongClickListener() {
+			
+			@Override
+			public boolean onLongClick(View v) {
+				
+				statusTv.setText(R.string.serverMode);
+				
+				isInServerMode = true;
+				enableServerMode();
+				return true;
+			}
+		});
+		
+		// Get a reference to the BluetoothAdapter and exit if not available
+		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+		if ( bluetoothAdapter == null ) finish();
+		
+		// Check if Bluetooth is enabled and launch an Intent through the system settings if not
+		if ( !bluetoothAdapter.isEnabled() ) {
+			
+			Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+			startActivityForResult(enableBluetooth, BLUETOOTH_ENABLE_REQ);
+		}
+		else {
+			
+			setButtonsEnabled(true);
+		}
+		
+		Toast.makeText(this, getString(R.string.appInfo), Toast.LENGTH_LONG)
+			.show();
+	}
+	
+	/**
+	 * Discovers Bluetooth devices that are in the local device's range (in a separate Thread).
+	 */
+	private void discoverNeighbours() {
+		
+		// Check whether there are already paired devices
+		Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
+		
+		ArrayList<String> pairedDevicesInfo = new ArrayList<String>();
+		
+		if ( pairedDevices.size() > 0 ) { 
+			
+			for ( BluetoothDevice device : pairedDevices ) { // Loop through the paired devices
+				
+				pairedDevicesInfo.add(device.getName() + "\n" + device.getAddress());
+			}
+		}
+		
+		// Start an Activity that shows a list of possible neighbours and allows the 
+					// user to select a device to connect to.
+		Intent listNeighboursIntent = BluetoothNeighboursListActivity
+				.getCallingIntent(this, pairedDevicesInfo);
+		startActivityForResult(listNeighboursIntent, BLUETOOTH_CHOOSE_NEIGHBOUR);
+	}
+	
+	/**
+	 * Configures the Bluetooth adapter in server mode (in a separate Thread).
+	 */
+	private void enableServerMode() {
+		
+		setButtonsEnabled(false);
+		new BluetoothAcceptConnectionThread(bluetoothConnectionHandler).start();
+	}
+	
+	@Override
+	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+		
+		// If the user did not enable Bluetooth exit
+		if ( requestCode == BLUETOOTH_ENABLE_REQ ) {
+			
+			if (resultCode == RESULT_OK)  {
+				setButtonsEnabled(true);
+			}
+			else {
+				finish();
+			}
+		}
+		// If the user has selected a Bluetooth device to connect to, initiate a connection request
+		else if ( requestCode == BLUETOOTH_CHOOSE_NEIGHBOUR ) {
+			
+			if ( resultCode == RESULT_OK ) {
+				
+				BluetoothDevice selectedDevice = data
+						.getParcelableExtra(
+								BluetoothDevice.EXTRA_DEVICE
+								);
+				connectToBluetoothDevice(selectedDevice);
+			}
+		}
+	}
+	
+	/**
+	 * Connects to a specific Bluetooth device.
+	 * 
+	 * @param device The device to connect to.
+	 */
+	private void connectToBluetoothDevice(BluetoothDevice device) {
+		
+		statusTv.setText(R.string.connecting);
+		progressBar.setVisibility(View.VISIBLE);
+		
+		// Start a new Thread to connect to the Bluetooth device since 
+		// a bluetooth connection is blocking!
+		new BluetoothConnectThread(device, bluetoothConnectionHandler)
+			.start();
+	}
+	
+	// Handler object to process incoming messages from worker threads.
+	Handler bluetoothConnectionHandler = new Handler(new Handler.Callback() {
+		
+		// Managing connection Thread
+		BluetoothManageConnectionThread connectionThread;
+		
+		@Override
+		public boolean handleMessage(Message msg) {
+			
+			switch (msg.what) {
+			// There has been an exception with the Bluetooth service. Inform the user.
+			case BLUETOOTH_ERROR:
+				
+				progressBar.setVisibility(View.INVISIBLE);
+				statusTv.setText(R.string.bluetoothError);
+				
+				bluetoothDataTv.setText((String) msg.obj);
+				break;
+				
+			// There has been a successful connection between two Bluetooth devices
+			case BLUETOOTH_SOCKET_CONNECTED:
+				
+				progressBar.setVisibility(View.INVISIBLE);
+				statusTv.setText(R.string.connected);
+				
+				connectionThread = (BluetoothManageConnectionThread) msg.obj;
+				
+				// If in client mode send some data to the server
+				if ( !isInServerMode ) {
+					String echoMessage = getString(R.string.echoMessage);
+					connectionThread.writeToSocket(echoMessage.getBytes());
+				}
+				
+				break;
+				
+			// Data has been received by one of the Bluetooth devices
+			case BLUETOOTH_DATA_RECEIVED:
+				// Display the data received from the server
+				String receivedData = (String) msg.obj;
+				bluetoothDataTv.setText(receivedData);
+				
+				// If in server mode, echo the received data
+				if ( isInServerMode ) {
+					connectionThread.writeToSocket(receivedData.getBytes());
+				}
+				break;
+
+			default:
+				break;
+			}
+			
+			return true;
+		}
+	});
+	
+	/**
+	 * Sets the state of the device discovery Button.
+	 * 
+	 * @param state Boolean indicating the state of the Button.
+	 */
+	private void setButtonsEnabled(boolean state) {
+		
+		deviceDiscoveryButton.setEnabled(state);
+	}
+}

+ 33 - 0
BluetoothNeighbourDiscovery/AndroidManifest.xml

@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.uab.android.bluetooth.simple"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+    
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".MainActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity 
+            android:name=".BluetoothNeighboursListActivity"
+            android:label="@string/app_name"/>
+    </application>
+
+</manifest>

BIN
BluetoothNeighbourDiscovery/ic_launcher-web.png


BIN
BluetoothNeighbourDiscovery/libs/android-support-v4.jar


BIN
BluetoothNeighbourDiscovery/res/drawable-hdpi/ic_launcher.png


BIN
BluetoothNeighbourDiscovery/res/drawable-mdpi/ic_launcher.png


BIN
BluetoothNeighbourDiscovery/res/drawable-xhdpi/ic_launcher.png


BIN
BluetoothNeighbourDiscovery/res/drawable-xxhdpi/ic_launcher.png


+ 17 - 0
BluetoothNeighbourDiscovery/res/layout/activity_main.xml

@@ -0,0 +1,17 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="${relativePackage}.${activityClass}" >
+
+    <Button
+        android:id="@+id/deviceDiscoveryBt"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentRight="true"
+        android:text="@string/discover"
+        android:enabled="false" />
+
+</RelativeLayout>

+ 11 - 0
BluetoothNeighbourDiscovery/res/layout/list_footerview.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/footer"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal"
+    android:text="@string/discoverFooterView"
+    android:textSize="20sp" >
+    
+
+</TextView>

+ 9 - 0
BluetoothNeighbourDiscovery/res/layout/list_item.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="10dp"
+    android:textSize="24sp" >
+    
+
+</TextView>

+ 11 - 0
BluetoothNeighbourDiscovery/res/values-v11/styles.xml

@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 12 - 0
BluetoothNeighbourDiscovery/res/values-v14/styles.xml

@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

+ 9 - 0
BluetoothNeighbourDiscovery/res/values/strings.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">BluetoothSimple</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="discover">Device discovery</string>
+    <string name="discoverFooterView">Discover more devices</string>
+
+</resources>

+ 20 - 0
BluetoothNeighbourDiscovery/res/values/styles.xml

@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

+ 133 - 0
BluetoothNeighbourDiscovery/src/org/uab/android/bluetooth/simple/BluetoothNeighboursListActivity.java

@@ -0,0 +1,133 @@
+package org.uab.android.bluetooth.simple;
+
+import java.util.ArrayList;
+
+import android.app.ListActivity;
+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.view.LayoutInflater;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+public class BluetoothNeighboursListActivity extends ListActivity {
+
+	static final String EXTRA_DEVICES = "EXTRA_DEVICES";
+	
+	BluetoothAdapter		bluetoothAdapter;
+	
+	ListView				neighboursListView;
+	ArrayAdapter<String> 	neighboursListAdapter;
+	
+	public static Intent getCallingIntent(Context context, ArrayList<String> devices) {
+		
+		Intent listNeighboursIntent = new Intent(context, BluetoothNeighboursListActivity.class);
+		listNeighboursIntent.putStringArrayListExtra(EXTRA_DEVICES, devices);
+		return listNeighboursIntent;
+	}
+	
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		
+		// Get a reference to the default BluetoothAdapter
+		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+		
+		// Get a reference to the ListView
+		neighboursListView = getListView();
+		
+		// Create a FooterView for the ListView
+		LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+		View footerView = layoutInflater.inflate(R.layout.list_footerview, neighboursListView, false);
+		
+		neighboursListView.setFooterDividersEnabled(true);
+		
+		// Add the FooterView to the list
+		neighboursListView.addFooterView(footerView, null, true);
+		
+		// Get the list of paired devices already discovered
+		ArrayList<String> pairedDevices = getIntent().getStringArrayListExtra(EXTRA_DEVICES);
+		
+		// Initialize the list's ArrayAdapter
+		neighboursListAdapter = new ArrayAdapter<String>(
+				this, 						// Context
+				R.layout.list_item, 		// View for the list items
+				pairedDevices				// Data objects
+				);
+		neighboursListView.setAdapter(neighboursListAdapter);
+		
+		// Set the ListView OnItemClickListener
+		neighboursListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+
+			@Override
+			public void onItemClick(AdapterView<?> parent, View view, int position,
+					long id) {
+				
+				// If the user clicked on the ListView's footer start discovering neighbours
+				if ( parent.getAdapter().getItemViewType(position) == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER ) {
+					
+					bluetoothAdapter.startDiscovery();
+				}
+				else {
+					
+					// Cancel neighbours discovery
+					bluetoothAdapter.cancelDiscovery();
+					
+					// Get the device's MAC Address
+					String selectedDevice = (String) parent.getItemAtPosition(position);
+					String macAddress = selectedDevice.split("\n")[1];
+					
+					BluetoothDevice bluetoothDevice = bluetoothAdapter.getRemoteDevice(macAddress);
+					
+					// Create an Intent to return the selected bluetooth device to the calling Activity
+					Intent dataIntent = new Intent();
+					dataIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, bluetoothDevice);
+					setResult(RESULT_OK, dataIntent);
+					finish();
+				}
+				
+			}
+		});
+	}
+	
+	@Override
+	protected void onResume() {
+		super.onResume();
+		
+		// Register a BroadcastReceiver for new devices discovery
+		IntentFilter discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+		registerReceiver(neighboursDiscoveryReceiver, discoveryFilter);
+	}
+	
+	@Override
+	protected void onPause() {
+		super.onPause();
+		
+		bluetoothAdapter.cancelDiscovery();
+		unregisterReceiver(neighboursDiscoveryReceiver);
+	}
+	
+	
+	BroadcastReceiver neighboursDiscoveryReceiver = new BroadcastReceiver() {
+		
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			
+			// A new Bluetooth device has been found
+			if ( intent.getAction().equals(BluetoothDevice.ACTION_FOUND) ) {
+				
+				BluetoothDevice device = intent
+						.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+				neighboursListAdapter.add(device.getName() + "\n" + device.getAddress());
+				neighboursListAdapter.notifyDataSetChanged();
+			}
+			
+		}
+	};
+}

+ 102 - 0
BluetoothNeighbourDiscovery/src/org/uab/android/bluetooth/simple/MainActivity.java

@@ -0,0 +1,102 @@
+package org.uab.android.bluetooth.simple;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+public class MainActivity extends Activity {
+	
+	static final int BLUETOOTH_ENABLE_REQ = 101;
+	static final int BLUETOOTH_CHOOSE_NEIGHBOUR = 102;
+	
+	BluetoothAdapter	bluetoothAdapter;
+	
+	Button				deviceDiscoveryButton;
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+		
+		deviceDiscoveryButton = (Button) findViewById(R.id.deviceDiscoveryBt);
+		deviceDiscoveryButton.setOnClickListener(new View.OnClickListener() {
+			
+			@Override
+			public void onClick(View v) {
+				
+				discoverNeighbours();
+			}
+		});
+		
+		// Get a reference to the BluetoothAdapter and exit if not available
+		bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+		if ( bluetoothAdapter == null ) finish();
+		
+		// Check if Bluetooth is enabled and launch an Intent through the system settings if not
+		if ( !bluetoothAdapter.isEnabled() ) {
+			
+			Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+			startActivityForResult(enableBluetooth, BLUETOOTH_ENABLE_REQ);
+		}
+		else {
+			
+			setButtonsEnabled(true);
+		}
+	}
+	
+	private void discoverNeighbours() {
+		
+		// Check whether there are already paired devices
+		Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
+		
+		ArrayList<String> pairedDevicesInfo = new ArrayList<String>();
+		
+		if ( pairedDevices.size() > 0 ) { 
+			
+			for ( BluetoothDevice device : pairedDevices ) { // Loop through the paired devices
+				
+				pairedDevicesInfo.add(device.getName() + "\n" + device.getAddress());
+			}
+		}
+		
+		// Start an Activity that shows a list of possible neighbours and allows the 
+					// user to select a device to connect to.
+		Intent listNeighboursIntent = BluetoothNeighboursListActivity
+				.getCallingIntent(this, pairedDevicesInfo);
+		startActivityForResult(listNeighboursIntent, BLUETOOTH_CHOOSE_NEIGHBOUR);
+	}
+	
+	@Override
+	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+		
+		// If the user did not enable Bluetooth exit
+		if ( requestCode == BLUETOOTH_ENABLE_REQ ) {
+			
+			if (resultCode == RESULT_OK)  {
+				setButtonsEnabled(true);
+			}
+			else {
+				finish();
+			}
+		}
+		else if ( requestCode == BLUETOOTH_CHOOSE_NEIGHBOUR ) {
+			
+			if ( resultCode == RESULT_OK ) {
+				
+				// TODO Connect to the Bluetooth device
+			}
+		}
+	}
+	
+	private void setButtonsEnabled(boolean state) {
+		
+		deviceDiscoveryButton.setEnabled(state);
+	}
+}