➤ Managing Bluetooth devices ➤ Discovering remote Bluetooth devices ➤ Managing discovery mode ➤ Communicating over Bluetooth ➤ Monitoring Internet connectivity ➤ Obeying user preferences
Trang 15. UpdateonCreatefurther to get references to each of the controls in the layout and
wire up the Spinner using the arrays defined in Step 3 Create two new stub methods,
savePreferencesandupdateUIFromPreferences, that will be updated to save the
auto-responder settings to a namedSharedPreferenceand apply the savedSharedPreferencestothe current UI, respectively
Spinner respondForSpinner;
CheckBox locationCheckbox;
Trang 25.2. Populate the Spinner to let users select the auto-responder expiry time.
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.respondForDisplayItems, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(
android.R.layout.simple_spinner_dropdown_item);
respondForSpinner.setAdapter(adapter);
5.3. Now wire up the OK and Cancel buttons to let users save or cancel setting changes
Button okButton = (Button) findViewById(R.id.okButton);
okButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
savePreferences();
setResult(RESULT_OK, null);
finish();
} });
Button cancelButton = (Button) findViewById(R.id.cancelButton); cancelButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view) {
5.4. Finally, make sure that when the Activity starts, it updates the GUI to represent the
private void savePreferences() {}
6. Next, complete the two stub methods from Step 5 Start withupdateUIFromPreferences; itshould read the current savedAutoResponderpreferences and apply them to the UI
Trang 3private void updateUIFromPreferences() {
// Get the saves settings
String preferenceName = getString(R.string.user_preferences);
SharedPreferences sp = getSharedPreferences(preferenceName, 0);
String autoResponsePref = getString(R.string.autoRespondPref);
String responseTextPref = getString(R.string.responseTextPref);
String autoLocPref = getString(R.string.includeLocationPref);
String respondForPref = getString(R.string.respondForPref);
boolean autoRespond = sp.getBoolean(autoResponsePref, false);
String respondText = sp.getString(responseTextPref, "");
boolean includeLoc = sp.getBoolean(includeLocPref, false);
int respondForIndex = sp.getInt(respondForPref, 0);
// Apply the saved settings to the UI
private void savePreferences() {
// Get the current settings from the UI
boolean autoRespond =
respondForSpinner.getSelectedItemPosition() > 0;
int respondForIndex = respondForSpinner.getSelectedItemPosition();
boolean includeLoc = locationCheckbox.isChecked();
String respondText = responseTextBox.getText().toString();
// Save them to the Shared Preference file
String preferenceName = getString(R.string.user_preferences);
Trang 48. ThesetAlarmstub from Step 7 is used to create a new Alarm that fires an Intent that shouldresult in the AutoResponder’s being disabled.
You’ll need to create a newAlarmobject and aBroadcastReceiverthat listens for it beforedisabling the auto-responder accordingly
8.1. Start by creating the action String that will represent the Alarm Intent
public static final String alarmAction =
"com.paad.emergencyresponder.AUTO_RESPONSE_EXPIRED";
8.2. Then create a new Broadcast Receiver instance that listens for an Intent that
includes the action specified in Step 8.1 When this Intent is received, it shouldmodify the auto-responder settings to disable the automatic response
private BroadcastReceiver stopAutoResponderReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(alarmAction)) { String preferenceName = getString(R.string.user_preferences); SharedPreferences sp = getSharedPreferences(preferenceName,0); Editor editor = sp.edit();
editor.putBoolean(getString(R.string.autoRespondPref), false); editor.commit();
} } };
8.3. Finally, complete thesetAlarmmethod It should cancel the existing alarm if the
auto-responder is turned off; otherwise, it should update the alarm with the latestexpiry time
PendingIntent intentToFire;
private void setAlarm(int respondForIndex) { // Create the alarm and register the alarm intent receiver.
AlarmManager alarms = (AlarmManager)getSystemService(ALARM_SERVICE);
if (intentToFire == null) { Intent intent = new Intent(alarmAction);
intentToFire = PendingIntent.getBroadcast(getApplicationContext(),
Trang 5else { // Otherwise find the length of time represented // by the selection and and set the alarm to // trigger after that time has passed.
Resources r = getResources();
int[] respondForValues = r.getIntArray(R.array.respondForValues);
int respondFor = respondForValues [respondForIndex];
9. That completes theAutoResponder, but before you can use it, you’ll need to add it to yourapplication manifest
private void startAutoResponder() {
startActivityForResult(new Intent(EmergencyResponder.this,
AutoResponder.class), 0);
Trang 6if (!requesters.contains(_from)) { lock.lock();
Trang 7String autoRespondPref = getString(R.string.autoRespondPref)
boolean autoRespond = prefs.getBoolean(autoRespondPref, false);
String respondText = prefs.getString(responseTextPref, "");
boolean includeLoc = prefs.getBoolean(includeLocationPref,
All code snippets in this example are part of the Chapter 12 Emergency Responder 2 project, available for download at Wrox.com.
You should now have a fully functional interactive and automated emergency responder
SUMMARY
The telephony stack is one of the fundamental technologies available on mobile phones While notall Android devices will necessarily provide telephony APIs, those that do are particularly versatileplatforms for person-to-person communication
Using the telephony APIs you learned how to initiate calls directly and through the dialer You alsodiscovered how to read and monitor phone, network, data, and SIM states
Android lets you use SMS to create applications that exchange data between devices and send andreceive text messages for your users
You also learned how to use Intents to allow the SMS applications already available on the phone tosend SMS and MMS messages on your behalf
Chapter 13 explores access to other device communication technologies You’ll investigate networkmanagement using Wi-Fi and explore the functionality available through the Bluetooth APIs
Trang 9Bluetooth, Networks, and Wi-Fi
WHAT’S IN THIS CHAPTER?
➤ Managing Bluetooth devices
➤ Discovering remote Bluetooth devices
➤ Managing discovery mode
➤ Communicating over Bluetooth
➤ Monitoring Internet connectivity
➤ Obeying user preferences for background data transfer
➤ Monitoring Wi-Fi and network details
➤ Configuring networks and Wi-Fi configurations
➤ Scanning for Wi-Fi access points
In this chapter you’ll continue to explore Android’s low-level communications APIs by ing the Bluetooth, network, and Wi-Fi packages
examin-Android offers APIs to manage and monitor your Bluetooth device settings, to control erability, to discover nearby Bluetooth devices, and to use Bluetooth as a proximity-based peer-to-peer transport layer for your applications
discov-A full network and Wi-Fi package is also available Using these discov-APIs you can scan for hotspots,create and modify Wi-Fi configuration settings, monitor your Internet connectivity, and controland monitor Internet settings and preferences
USING BLUETOOTH
In this section you’ll learn how to interact with the local Bluetooth device and communicatewith remote devices on nearby phones
Trang 10Using Bluetooth you can search for, and connect to, other devices within range By initiating a munications link using Bluetooth Sockets you can then transmit and receive streams of data betweendevices from within your applications.
com-The Bluetooth libraries have been available in Android only since Android version
2.0 (SDK API level 5) It’s also important to remember that not all Android devices
will necessarily include Bluetooth hardware.
Bluetooth is a communications protocol designed for short-range, low-bandwidth peer-to-peer munications As of Android 2.1, only encrypted communication is supported, meaning you can onlyform connections between paired devices In Android, Bluetooth devices and connections are handled
com-by the following classes:
➤ BluetoothAdapter The Bluetooth Adapter represents the local Bluetooth device — that is,the Android device on which your application is running
➤ BluetoothDevice Each remote device with which you wish to communicate is represented
as aBluetoothDevice
➤ BluetoothSocket CallcreateRfcommSocketToServiceRecordon a remote Bluetooth Deviceobject to create a Bluetooth Socket that will let you make a connection request to the remotedevice, and then initiate communications
➤ BluetoothServerSocket By creating a Bluetooth Server Socket (using the
listenUsingRfcommWithServiceRecordmethod) on your local Bluetooth Adapter, you canlisten for incoming connection requests from Bluetooth Sockets on remote devices
Accessing the Local Bluetooth Device Adapter
The local Bluetooth device is controlled via theBluetoothAdapterclass
To access the default Bluetooth adapter on the host device callgetDefaultAdapter, as shown in ing 13-1 It is possible that some Android devices will feature multiple Bluetooth adapters, though it iscurrently only possible to access the default device
List-LISTING 13-1: Accessing the default Bluetooth Adapter
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
To read any of the local Bluetooth Adapter properties, initiate discovery, or find bonded devices youwill need to include theBLUETOOTHmanifest permission In order to modify any of the local deviceproperties theBLUETOOTH_ADMINuses-permission is also required
<uses-permission android:name="android.permission.BLUETOOTH"/>
Trang 11Managing Bluetooth Properties and State
The Bluetooth Adapter offers methods for reading and setting properties of the local Bluetoothhardware
The Bluetooth Adapter properties can be read and changed only if the Bluetooth
adapter is currently turned on (that is, if its device state is enabled) If the device is
off, these methods will returnnull.
If the Bluetooth Adapter is turned on, and you have included theBLUETOOTHpermission in your
man-ifest, you can access the Bluetooth Adapter’s friendly name (an arbitrary string that users can set and
then use to identify a particular device) and hardware address, as shown in Listing 13-2
Use theisEnabledmethod, as shown in Listing 13-2, to confirm the device is enabled before accessingthese properties
LISTING 13-2: Reading Bluetooth Adapter properties
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
String toastText;
if (bluetooth.isEnabled()) {
String address = bluetooth.getAddress();
String name = bluetooth.getName();
toastText = name + " : " + address;
}
else
toastText = "Bluetooth is not enabled";
Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();
If you also have theBLUETOOTH_ADMINpermission you can change the friendly name of the BluetoothAdapter using thesetNamemethod:
Trang 12To enable the Bluetooth Adapter you can start a system sub-Activity using theACTION_REQUEST_ENABLEBluetooth Adapter static constant as astartActivityForResultaction string:
String enableBT = BluetoothAdapter.ACTION_REQUEST_ENABLE;
startActivityForResult(new Intent(enableBT), 0);
The sub-Activity is shown in Figure 13-1 It prompts the user to turn on Bluetooth and asks for firmation If the user agrees, the sub-Activity will close and return to the calling Activity once theBluetooth Adapter has turned on (or has encountered an error) If the user selects no, the sub-Activitywill close and return immediately Use the result code parameter returned in theonActivityResulthandler to determine the success of this operation
con-FIGURE 13-1
It is also possible to turn the Bluetooth Adapter on and off directly, using the
enableanddisablemethods, if you include theBLUETOOTH_ADMINpermission in
your manifest.
Note that this should be done only when absolutely necessary and that the user
should always be notified if you are manually changing the Bluetooth Adapter
status on the user’s behalf In most cases you should use the Intent mechanism
described earlier.
Trang 13Enabling and disabling the Bluetooth Adapter are somewhat time-consuming, asynchronous tions Rather than polling the Bluetooth Adapter, your application should register a Broadcast Receiverthat listens forACTION_STATE_CHANGED The broadcast Intent will include two extras,EXTRA_STATEandEXTRA_PREVIOUS_STATE, which indicate the current and previous Bluetooth Adapter states,
opera-respectively
Listing 13-3 shows how to use an Intent to prompt the user to enable Bluetooth and a BroadcastReceiver to track changes in the Bluetooth Adapter status
LISTING 13-3: Enabling Bluetooth and tracking the adapter state
BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
BroadcastReceiver bluetoothState = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String prevStateExtra = BluetoothAdapter.EXTRA_PREVIOUS_STATE;
String stateExtra = BluetoothAdapter.EXTRA_STATE;
int state = intent.getIntExtra(stateExtra, −1);
int previousState = intent.getIntExtra(prevStateExtra, −1);
String actionStateChanged = BluetoothAdapter.ACTION_STATE_CHANGED;
String actionRequestEnable = BluetoothAdapter.ACTION_REQUEST_ENABLE;
registerReceiver(bluetoothState,
new IntentFilter(actionStateChanged));
startActivityForResult(new Intent(actionRequestEnable), 0);
Trang 14Being Discoverable and Remote Device Discovery
The process of two devices finding each other in order to connect is called discovery Before you can
establish a Bluetooth Socket for communications, the local Bluetooth Adapter must bond with theremote device Before two devices can bond and connect, they first need to discover each other
While the Bluetooth protocol supports ad-hoc connections for data transfer, this
mechanism is not currently available in Android Android Bluetooth
communication is currently supported only between bonded devices.
Managing Device Discoverability
FIGURE 13-2
In order for remote Android Devices to find your local
Blue-tooth Adapter during a discovery scan, you need to ensure
that it is discoverable
The Bluetooth Adapter’s discoverability is indicated by its
scan mode You can find the adapter’s scan mode by calling
getScanModeon theBluetoothAdapterobject It will return
one of the followingBluetoothAdapterconstants:
➤ SCAN_MODE_CONNECTABLE_DISCOVERABLE Inquiry
scan and page scan are both enabled, meaning
that the device is discoverable from any Bluetooth
device performing a discovery scan
➤ SCAN_MODE_CONNECTABLE Page Scan is enabled
but inquiry scan is not This means that devices
that have previously connected and bonded to the
local device can find it during discovery, but new
devices can’t
➤ SCAN_MODE_NONE Discoverability is turned off
No remote devices can find the local adapter
dur-ing discovery
For privacy reasons, Android devices will default to
having discoverability disabled To turn on discovery you
need to obtain explicit permission from the user; you do this by starting a new Activity using theACTION_REQUEST_DISCOVERABLEaction:
String aDiscoverable = BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE;
startActivityForResult(new Intent(aDiscoverable),
DISCOVERY_REQUEST);
By default discoverability will be enabled for two minutes You can modify this setting by adding anEXTRA_DISCOVERABLE_DURATIONextra to the launch Intent, specifying the number of seconds you wantdiscoverability to last
When the Intent is broadcast the user will be prompted by the dialog shown in Figure 13-2 to turndiscoverability on for the specified duration
Trang 15To learn if the user has allowed or rejected your discovery request, override theonActivityResulthandler, as shown in Listing 13-4 The returnedresultCodeparameter indicates the duration of dis-coverability, or a negative number if the user has rejected your request.
LISTING 13-4: Monitoring discoverability modes
@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == DISCOVERY_REQUEST) {
boolean isDiscoverable = resultCode > 0;
int discoverableDuration = resultCode;
}
}
Alternatively you can monitor changes in discoverability by receiving theACTION_SCAN_MODE_CHANGEDbroadcast action, as shown in Listing 13-5 The broadcast Intent includes the current and previous scanmodes as extras
LISTING 13-5: Monitoring discoverability modes
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String prevScanMode = BluetoothAdapter.EXTRA_PREVIOUS_SCAN_MODE;
String scanMode = BluetoothAdapter.EXTRA_SCAN_MODE;
int scanMode = intent.getIntExtra(scanMode, −1);
int prevMode = intent.getIntExtra(prevScanMode, −1);
}
},
new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
Discovering Remote Devices
In this section you’ll now learn how to initiate discovery from your local adapter to find discoverabledevices nearby
The discovery process can take some time to complete (up to 12 seconds) During
this time, performance of your Bluetooth Adapter communications will be
seriously degraded Use the techniques in this section to check and monitor the
discovery status of the Bluetooth Adapter, and avoid doing high-bandwidth
operations (including connecting to a new remote Bluetooth Device) while
discovery is in progress.
You can check to see if the local Bluetooth Adapter is already performing a discovery scan using theisDiscoveringmethod
Trang 16To initiate the discovery process callstartDiscoveryon the Bluetooth Adapter To cancel a discovery
in progress callcancelDiscovery
LISTING 13-6: Monitoring discovery
BroadcastReceiver discoveryMonitor = new BroadcastReceiver() {
String dStarted = BluetoothAdapter.ACTION_DISCOVERY_STARTED;
String dFinished = BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
LISTING 13-7: Discovering remote Bluetooth Devices
BroadcastReceiver discoveryResult = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String remoteDeviceName =
Trang 17BluetoothDevice remoteDevice;
remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(getApplicationContext(),
"Discovered: " + remoteDeviceName, Toast.LENGTH_SHORT).show();
// TODO Do something with the remote Bluetooth Device.
Bluetooth Communications
The Bluetooth communications APIs are wrappers around RFCOMM, the Bluetooth radio frequencycommunications protocol RFCOMM supports RS232 serial communication over the Logical LinkControl and Adaptation Protocol (L2CAP) layer
In practice, this alphabet soup provides a mechanism for opening communication sockets between twopaired Bluetooth devices
Before your application can communicate between devices they must be paired
(bonded) At the time of writing (Android API level 7) there is no way to manually
initiate pairing between the local Bluetooth Adapter and a remote Bluetooth
Device.
If two devices are to be paired the user will need to explicitly allow this, either
through the Bluetooth Settings screen or when prompted by your application when
you attempt to connect a Bluetooth Socket between two unpaired devices.
You can establish an RFCOMM communication channel for bidirectional communications using thefollowing classes
➤ BluetoothServerSocket Used to establish a listening socket for initiating a link betweendevices To establish a handshake, one device acts as a server to listen for, and accept, incom-ing connection requests
➤ BluetoothSocket Used in creating a new client socket to connect to a listening BluetoothServer Socket, and returned by the Server Socket once a connection is established Once theconnection is made, Bluetooth Sockets are used on both the server and client sides to transferdata streams
Trang 18When creating an application that uses Bluetooth as a peer-to-peer transport layer, you’ll need toimplement both a Bluetooth Server Socket to listen for connections and a Bluetooth Socket to initiate anew channel and handle communications.
Once connected, the Socket Server returns a Bluetooth Socket that’s subsequently used by the serverdevice to send and receive data This server-side Bluetooth Socket is used in exactly the same way
as the client socket The designations of server and client are relevant only to how the connection is
established They don’t affect how data flows once that connection is made
Opening a Bluetooth Server Socket Listener
FIGURE 13-3
A Bluetooth Server Socket is used to listen for incoming
Bluetooth Socket connection requests from remote Bluetooth
Devices In order for two Bluetooth devices to be connected,
one must act as a server (listening for and accepting incoming
requests) and the other as a client (initiating the request to
connect to the server)
Once the two are connected, the communications between
the server and host device are handled through a Bluetooth
Socket at both ends
To listen for incoming connection requests call the
listenUsingRfcommWithServiceRecordmethod on your
Bluetooth Adapter, passing in both a string ‘‘name’’ to
iden-tify your server and a UUID (universally unique identifier)
This will return aBluetoothServerSocketobject Note that
the client Bluetooth Socket that connects to this listener will
need to know the UUID in order to connect
To start listening for connections callaccepton this Server
Socket, optionally passing in a timeout duration The Server
Socket will now block until a remote Bluetooth Socket client
with a matching UUID attempts to connect If a connection
request is made from a remote device that is not yet paired
with the local adapter, the user will be prompted to accept a
pairing request before the accept call returns This prompt is
made via a notification, as shown in Figure 13-3
If an incoming connection request is successful,acceptwill return a Bluetooth Socket connected to theclient device You can use this socket to transfer data, as shown later in this section
Note thatacceptis a blocking operation, so it’s best practice to listen for incoming
connection requests on a background thread rather than block the UI thread until a
connection has been made.
It’s also important to note that your Bluetooth Adapter must be discoverable for remote tooth Devices to connect to it Listing 13-8 shows some typical skeleton code that uses the
Blue-ACTION_REQUEST_DISCOVERABLEbroadcast to request that the device be made discoverable, beforelistening for incoming connection requests for the returned discoverability duration
Trang 19LISTING 13-8: Listening for Bluetooth Socket connection requests
startActivityForResult(new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE),
DISCOVERY_REQUEST);
@Override
protected void onActivityResult(int requestCode,
int resultCode, Intent data) {
if (requestCode == DISCOVERY_REQUEST) {
boolean isDiscoverable = resultCode > 0;
int discoverableDuration = resultCode;
if (isDiscoverable) {
UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666");
String name = "bluetoothserver";
final BluetoothServerSocket btserver =
bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);
Thread acceptThread = new Thread(new Runnable() {
public void run() { try {
// Block until client connection established.
BluetoothSocket serverSocket = btserver.accept();
// TODO Transfer data using the server socket } catch (IOException e) {
Log.d("BLUETOOTH", e.getMessage());
} } });
acceptThread.start();
}
}
}
Selecting Remote Bluetooth Devices for Communications
TheBluetoothSocketclass is used on the client device to initiate a communications channel fromwithin your application to a listening Bluetooth Server Socket
You create client-side Bluetooth Sockets by callingcreateRfcommSocketToServiceRecordon a
BluetoothDeviceobject That object represents the target remote server device It should have aBluetooth Server Socket listening for connection requests (as described in the previous section)
There are a number of ways to obtain a reference to a remote Bluetooth Device, and some importantcaveats regarding the devices with which you can create a communications link
Bluetooth Device Connection Requirements
In order for a Bluetooth Socket to establish a connection to a remote Bluetooth Device, the followingconditions must be true:
➤ The remote device must be discoverable
➤ The remote device must accept connections using a Bluetooth Server Socket
➤ The local and remote devices must be paired (or bonded) If the devices are not paired, theuser will be prompted to pair them when you initiate the connection request
Trang 20Finding a Bluetooth Device to Connect To
Each Bluetooth Device object represents a remote device These objects are used to obtain remotedevice properties and to initiate Bluetooth Socket connections There are several ways for you to obtain
aBluetoothDeviceobject in code
In each case you should check to ensure that the device you intend to connect to is discoverable, and(optionally) determine whether you are bonded to it If you can’t discover the remote device, you shouldprompt the user to enable discoverability on it
You learned one technique for finding discoverable Bluetooth Devices earlier in this section using thestartDiscoverymethod and monitoringACTION_FOUNDbroadcasts You learned that each receivedbroadcast includes aBluetoothDevice.EXTRA_DEVICEextra that contains the discovered BluetoothDevice
You can also use thegetRemoteDevicemethod on your local Bluetooth Adapter, specifying the ware address of the remote Bluetooth Device you want to connect to
hard-BluetoothDevice device = bluetooth.getRemoteDevice("01:23:77:35:2F:AA");
To find the set of currently paired devices callgetBondedDeviceson the local Bluetooth Adapter Youcan query the returned set to find out if a target Bluetooth Device is paired with the local adapter
Set<BluetoothDevice> bondedDevices = bluetooth.getBondedDevices();
if (bondedDevices.contains(remoteDevice))
// TODO Target device is bonded / paired with the local device.
Listing 13-9 shows a typical implementation pattern that checks a given Bluetooth Device for ability and pairing
discover-LISTING 13-9: Checking remote devices for discoverability and pairing
final BluetoothDevice device =
bluetooth.getRemoteDevice("01:23:77:35:2F:AA");
final Set<BluetoothDevice> bondedDevices = bluetooth.getBondedDevices();
BroadcastReceiver discoveryResult = new BroadcastReceiver() {
};
registerReceiver(discoveryResult,
new IntentFilter(BluetoothDevice.ACTION_FOUND));
Trang 21if (!bluetooth.isDiscovering())
bluetooth.startDiscovery();
Opening a Client Bluetooth Socket Connection
FIGURE 13-4
To initiate a communications channel to a remote device,
create a Bluetooth Socket from theBluetoothDeviceobject
that represents it
To create a new connection callcreateRfcommSocket
ToServiceRecordon the Bluetooth Device to connect to,
passing in the UUID of the Bluetooth Server Socket accepting
requests
If you attempt to connect to a Bluetooth Device that has
not yet been paired (bonded) with the host device, you will
be prompted to accept the pairing before theconnectcall
completes, as shown in Figure 13-4
The user must accept the pairing request on both the host
and remote devices for the connection to be
established
The returned Bluetooth Socket can then be used to
initiate the connection with a call toconnect, as shown in
Listing 13-10
Note thatconnectis a blocking operation, so it’s best practice to initiate
connection requests on a background thread rather than block the UI thread until a
connection has been made.
LISTING 13-10: Connecting to a remote Bluetooth server
Trang 22Transmitting Data Using Bluetooth Sockets
Once a connection has been established, you will have a Bluetooth Socket on both the client and theserver devices From this point onward there is no significant distinction between them: you can sendand receive data using the Bluetooth Socket on both devices
Data transfer across Bluetooth Sockets is handled via standard JavaInputStreamandOutputStreamobjects, which you can obtain from a Bluetooth Socket using the appropriately namedgetInputStreamandgetOutputStreammethods, respectively
Listing 13-11 shows two simple skeleton methods, the first used to send a string to a remote deviceusing an Output Stream, and the second to listen for incoming strings using an Input Stream The sametechnique can be used to transfer any streamable data
LISTING 13-11: Sending and receiving strings using Bluetooth Sockets
private void sendMessage(String message){
OutputStream outStream;
try {
outStream = socket.getOutputStream();
// Add a stop character.
byte[] byteArray = (message + " ").getBytes();
message = message + new String(buffer, 0, bytesRead);
bytesRead = instream.read(buffer);
} message = message + new String(buffer, 0, bytesRead − 1);
return result;
} }
Trang 23} catch (IOException e) {}
return result;
}
Bluetooth Data Transfer Example
The following example uses the Android Bluetooth APIs to construct a simple peer-to-peer messagingsystem that works between two paired Bluetooth devices
Unfortunately the Android emulator can’t currently be used to test Bluetooth functionality In order totest this application you will need to have two physical devices
1. Start by creating a newBluetoothTextingproject featuring aBluetoothTextingActivity.Modify the manifest to includeBLUETOOTHandBLUETOOTH_ADMINpermissions
dis-Also include Text View and Edit Text controls to use for reading and writing messages acrossthe connection
Trang 24<EditText android:id="@+id/text_message"
android:text="Search for listener"
android:text="Listen for connection"
3. Override theonCreatemethod of theBluetoothTextingActivity Make calls to a collection
of stub methods that will be used to access the Bluetooth device and wire up the UI controls.import java.io.IOException;
Trang 25private void configureBluetooth() {}
private void setupListenButton() {}
private void setupListView() {}
private void setupSearchButton() {}
}
4. Fill in theconfigureBluetoothstub to get access to the local Bluetooth Adapter and store
it in a field variable Take this opportunity to create a field variable for a Bluetooth Socket.This will be used to store either the server or client communications socket once a channelhas been established You should also define a UUID to identify your application when con-nections are being established
private BluetoothAdapter bluetooth;
private BluetoothSocket socket;
private UUID uuid = UUID.fromString("a60f35f0-b93a-11de-8a39-08002009c666");
private void configureBluetooth() {
bluetooth = BluetoothAdapter.getDefaultAdapter();