Sunday 14 August 2011

tutorial for spinner in android

/*

* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package com.android.example.spinner;

import com.android.example.spinner.R;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

/**
* Displays an Android spinner widget backed by data in an array. The
* array is loaded from the strings.xml resources file.
*/

public class SpinnerActivity extends Activity {

/**
* Fields to contain the current position and display contents of the spinner
*/

protected int mPos;
protected String mSelection;

/**
* ArrayAdapter connects the spinner widget to array-based data.
*/

protected ArrayAdapter<CharSequence> mAdapter;

/**
* The initial position of the spinner when it is first installed.
*/

public static final int DEFAULT_POSITION = 2;

/**
* The name of a properties file that stores the position and
* selection when the activity is not loaded.
*/

public static final String PREFERENCES_FILE = "SpinnerPrefs";

/**
* These values are used to read and write the properties file.
* PROPERTY_DELIMITER delimits the key and value in a Java properties file.
* The "marker" strings are used to write the properties into the file
*/

public static final String PROPERTY_DELIMITER = "=";

/**
* The key or label for "position" in the preferences file
*/

public static final String POSITION_KEY = "Position";

/**
* The key or label for "selection" in the preferences file
*/

public static final String SELECTION_KEY = "Selection";

public static final String POSITION_MARKER =
POSITION_KEY
+ PROPERTY_DELIMITER;

public static final String SELECTION_MARKER =
SELECTION_KEY
+ PROPERTY_DELIMITER;

/**
* Initializes the application and the activity.
* 1) Sets the view
* 2) Reads the spinner's backing data from the string resources file
* 3) Instantiates a callback listener for handling selection from the
* spinner
* Notice that this method includes code that can be uncommented to force
* tests to fail.
*
* This method overrides the default onCreate() method for an Activity.
*
* @see android.app.Activity#onCreate(android.os.Bundle)
*/

@Override
public void onCreate(Bundle savedInstanceState) {

/**
* derived classes that use onCreate() overrides must always call the super constructor
*/

super.onCreate(savedInstanceState);

setContentView
(R.layout.main);

Spinner spinner = (Spinner) findViewById(R.id.Spinner01);

/*
* Create a backing mLocalAdapter for the Spinner from a list of the
* planets. The list is defined by XML in the strings.xml file.
*/


this.mAdapter = ArrayAdapter.createFromResource(this, R.array.Planets,
android
.R.layout.simple_spinner_dropdown_item);

/*
* Attach the mLocalAdapter to the spinner.
*/


spinner
.setAdapter(this.mAdapter);

/*
* Create a listener that is triggered when Android detects the
* user has selected an item in the Spinner.
*/


OnItemSelectedListener spinnerListener = new myOnItemSelectedListener(this,this.mAdapter);

/*
* Attach the listener to the Spinner.
*/


spinner
.setOnItemSelectedListener(spinnerListener);


/*
* To demonstrate a failure in the preConditions test,
* uncomment the following line.
* The test will fail because the selection listener for the
* Spinner is not set.
*/

// spinner.setOnItemSelectedListener(null);

}


/**
* A callback listener that implements the
* {@link android.widget.AdapterView.OnItemSelectedListener} interface
* For views based on adapters, this interface defines the methods available
* when the user selects an item from the View.
*
*/

public class myOnItemSelectedListener implements OnItemSelectedListener {

/*
* provide local instances of the mLocalAdapter and the mLocalContext
*/


ArrayAdapter<CharSequence> mLocalAdapter;
Activity mLocalContext;

/**
* Constructor
* @param c - The activity that displays the Spinner.
* @param ad - The Adapter view that
* controls the Spinner.
* Instantiate a new listener object.
*/

public myOnItemSelectedListener(Activity c, ArrayAdapter<CharSequence> ad) {

this.mLocalContext = c;
this.mLocalAdapter = ad;

}

/**
* When the user selects an item in the spinner, this method is invoked by the callback
* chain. Android calls the item selected listener for the spinner, which invokes the
* onItemSelected method.
*
* @see android.widget.AdapterView.OnItemSelectedListener#onItemSelected(
* android.widget.AdapterView, android.view.View, int, long)
* @param parent - the AdapterView for this listener
* @param v - the View for this listener
* @param pos - the 0-based position of the selection in the mLocalAdapter
* @param row - the 0-based row number of the selection in the View
*/

public void onItemSelected(AdapterView parent, View v, int pos, long row) {

SpinnerActivity.this.mPos = pos;
SpinnerActivity.this.mSelection = parent.getItemAtPosition(pos).toString();
/*
* Set the value of the text field in the UI
*/

TextView resultText = (TextView)findViewById(R.id.SpinnerResult);
resultText
.setText(SpinnerActivity.this.mSelection);
}

/**
* The definition of OnItemSelectedListener requires an override
* of onNothingSelected(), even though this implementation does not use it.
* @param parent - The View for this Listener
*/

public void onNothingSelected(AdapterView parent) {

// do nothing

}
}

/**
* Restores the current state of the spinner (which item is selected, and the value
* of that item).
* Since onResume() is always called when an Activity is starting, even if it is re-displaying
* after being hidden, it is the best place to restore state.
*
* Attempts to read the state from a preferences file. If this read fails,
* assume it was just installed, so do an initialization. Regardless, change the
* state of the spinner to be the previous position.
*
* @see android.app.Activity#onResume()
*/

@Override
public void onResume() {

/*
* an override to onResume() must call the super constructor first.
*/


super.onResume();

/*
* Try to read the preferences file. If not found, set the state to the desired initial
* values.
*/


if (!readInstanceState(this)) setInitialState();

/*
* Set the spinner to the current state.
*/


Spinner restoreSpinner = (Spinner)findViewById(R.id.Spinner01);
restoreSpinner
.setSelection(getSpinnerPosition());

}

/**
* Store the current state of the spinner (which item is selected, and the value of that item).
* Since onPause() is always called when an Activity is about to be hidden, even if it is about
* to be destroyed, it is the best place to save state.
*
* Attempt to write the state to the preferences file. If this fails, notify the user.
*
* @see android.app.Activity#onPause()
*/

@Override
public void onPause() {

/*
* an override to onPause() must call the super constructor first.
*/


super.onPause();

/*
* Save the state to the preferences file. If it fails, display a Toast, noting the failure.
*/


if (!writeInstanceState(this)) {
Toast.makeText(this,
"Failed to write state!", Toast.LENGTH_LONG).show();
}
}

/**
* Sets the initial state of the spinner when the application is first run.
*/

public void setInitialState() {

this.mPos = DEFAULT_POSITION;

}

/**
* Read the previous state of the spinner from the preferences file
* @param c - The Activity's Context
*/

public boolean readInstanceState(Context c) {

/*
* The preferences are stored in a SharedPreferences file. The abstract implementation of
* SharedPreferences is a "file" containing a hashmap. All instances of an application
* share the same instance of this file, which means that all instances of an application
* share the same preference settings.
*/


/*
* Get the SharedPreferences object for this application
*/


SharedPreferences p = c.getSharedPreferences(PREFERENCES_FILE, MODE_WORLD_READABLE);
/*
* Get the position and value of the spinner from the file, or a default value if the
* key-value pair does not exist.
*/

this.mPos = p.getInt(POSITION_KEY, SpinnerActivity.DEFAULT_POSITION);
this.mSelection = p.getString(SELECTION_KEY, "");

/*
* SharedPreferences doesn't fail if the code tries to get a non-existent key. The
* most straightforward way to indicate success is to return the results of a test that
* SharedPreferences contained the position key.
*/


return (p.contains(POSITION_KEY));

}

/**
* Write the application's current state to a properties repository.
* @param c - The Activity's Context
*
*/

public boolean writeInstanceState(Context c) {

/*
* Get the SharedPreferences object for this application
*/


SharedPreferences p =
c
.getSharedPreferences(SpinnerActivity.PREFERENCES_FILE, MODE_WORLD_READABLE);

/*
* Get the editor for this object. The editor interface abstracts the implementation of
* updating the SharedPreferences object.
*/


SharedPreferences.Editor e = p.edit();

/*
* Write the keys and values to the Editor
*/


e
.putInt(POSITION_KEY, this.mPos);
e
.putString(SELECTION_KEY, this.mSelection);

/*
* Commit the changes. Return the result of the commit. The commit fails if Android
* failed to commit the changes to persistent storage.
*/


return (e.commit());

}

public int getSpinnerPosition() {
return this.mPos;
}

public void setSpinnerPosition(int pos) {
this.mPos = pos;
}

public String getSpinnerSelection() {
return this.mSelection;
}

public void setSpinnerSelection(String selection) {
this.mSelection = selection;
}
}

tutorial for radiogroup and radio button

Using RadioGroups and RadioButtons, You often use radio buttons when a user should be allowed to only select one item from a small group of items. For instance, a question asking for gender can give three options: male, female, and unspecified. Only one of these options should be checked at a time.The RadioButton objects are similar to CheckBox objects.They have a text label next to them, set via the text attribute, and they have a state (checked or unchecked). However, you can 148 Chapter 7 Exploring User Interface Screen Elements group RadioButton objects inside a RadioGroup that handles enforcing their combined states so that only one RadioButton can be checked at a time. If the user selects a RadioButton that is already checked, it does not become unchecked. However, you can provide the user with an action to clear the state of the entire RadioGroup so that none of the buttons are checked.

Here we have an XML layout resource with a RadioGroup containing four RadioButton objects (shown in Figure 7.7, toward the bottom of the screen).The RadioButton objects have text labels,“Option 1,” and so on.The XML layout resource definition is shown here:


You handle actions on these RadioButton objects through the RadioGroup object.The following example shows registering for clicks on the RadioButton objects within the


RadioGroup:
final RadioGroup group = (RadioGroup)findViewById(R.id.RadioGroup01);
final TextView tv = (TextView)
findViewById(R.id.TextView01);
group.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
public void onCheckedChanged(
Using Buttons, Check Boxes, and Radio Groups 149
RadioGroup group, int checkedId) {
if (checkedId != -1) {
RadioButton rb = (RadioButton)
findViewById(checkedId);
if (rb != null) {
tv.setText(“You chose: “ + rb.getText());
}
} else {
tv.setText(“Choose 1”);
}
}
});

As this layout example demonstrates, there is nothing special that you need to do to make the RadioGroup and internal RadioButton objects work properly.The preceding code illustrates how to register to receive a notification whenever the RadioButton selection
changes.

The code demonstrates that the notification contains the resource identifier for the specific RadioButton that the user chose, as assigned in the layout file.To do something interesting with this, you need to provide a mapping between this resource identifier (or the text label) to the corresponding functionality in your code. In the example,we query for the button that was selected, get its text, and assign its text to another TextView control that we have on the screen.

As mentioned, the entire RadioGroup can be cleared so that none of the RadioButton objects are selected.The following example demonstrates how to do this in response to a button click outside of the RadioGroup:

final Button clear_choice = (Button) findViewById(R.id.Button01);
clear_choice.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
RadioGroup group = (RadioGroup)
findViewById(R.id.RadioGroup01);
if (group != null) {
group.clearCheck();
}
}
}

The action of calling the clearCheck() method triggers a call to the onCheckedChangedListener() callback method.This is why we have to make sure that the resource identifier we received is valid. Right after a call to the clearCheck() method, it is not a valid identifier but instead is set to the value -1 to indicate that no RadioButton is currently checked.

Download android software n game


www.androidmarket.com

Friday 12 August 2011

Tutorial for Bluetooth

BluetoothChat

/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package com.example.android.BluetoothChat;

import android.app.ActionBar;
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.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

/**
* This is the main Activity that displays the current chat session.
*/

public class BluetoothChat extends Activity {
// Debugging
private static final String TAG = "BluetoothChat";
private static final boolean D = true;

// Message types sent from the BluetoothChatService Handler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;

// Key names received from the BluetoothChatService Handler
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";

// Intent request codes
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
private static final int REQUEST_ENABLE_BT = 3;

// Layout Views
private ListView mConversationView;
private EditText mOutEditText;
private Button mSendButton;

// Name of the connected device
private String mConnectedDeviceName = null;
// Array adapter for the conversation thread
private ArrayAdapter<String> mConversationArrayAdapter;
// String buffer for outgoing messages
private StringBuffer mOutStringBuffer;
// Local Bluetooth adapter
private BluetoothAdapter mBluetoothAdapter = null;
// Member object for the chat services
private BluetoothChatService mChatService = null;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(D) Log.e(TAG, "+++ ON CREATE +++");

// Set up the window layout
setContentView
(R.layout.main);

// Get local Bluetooth adapter
mBluetoothAdapter
= BluetoothAdapter.getDefaultAdapter();

// If the adapter is null, then Bluetooth is not supported
if (mBluetoothAdapter == null) {
Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
finish
();
return;
}
}

@Override
public void onStart() {
super.onStart();
if(D) Log.e(TAG, "++ ON START ++");

// If BT is not on, request that it be enabled.
// setupChat() will then be called during onActivityResult
if (!mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult
(enableIntent, REQUEST_ENABLE_BT);
// Otherwise, setup the chat session
} else {
if (mChatService == null) setupChat();
}
}

@Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");

// Performing this check in onResume() covers the case in which BT was
// not enabled during onStart(), so we were paused to enable it...
// onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
if (mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService
.start();
}
}
}

private void setupChat() {
Log.d(TAG, "setupChat()");

// Initialize the array adapter for the conversation thread
mConversationArrayAdapter
= new ArrayAdapter<String>(this, R.layout.message);
mConversationView
= (ListView) findViewById(R.id.in);
mConversationView
.setAdapter(mConversationArrayAdapter);

// Initialize the compose field with a listener for the return key
mOutEditText
= (EditText) findViewById(R.id.edit_text_out);
mOutEditText
.setOnEditorActionListener(mWriteListener);

// Initialize the send button with a listener that for click events
mSendButton
= (Button) findViewById(R.id.button_send);
mSendButton
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// Send a message using content of the edit text widget
TextView view = (TextView) findViewById(R.id.edit_text_out);
String message = view.getText().toString();
sendMessage
(message);
}
});

// Initialize the BluetoothChatService to perform bluetooth connections
mChatService
= new BluetoothChatService(this, mHandler);

// Initialize the buffer for outgoing messages
mOutStringBuffer
= new StringBuffer("");
}

@Override
public synchronized void onPause() {
super.onPause();
if(D) Log.e(TAG, "- ON PAUSE -");
}

@Override
public void onStop() {
super.onStop();
if(D) Log.e(TAG, "-- ON STOP --");
}

@Override
public void onDestroy() {
super.onDestroy();
// Stop the Bluetooth chat services
if (mChatService != null) mChatService.stop();
if(D) Log.e(TAG, "--- ON DESTROY ---");
}

private void ensureDiscoverable() {
if(D) Log.d(TAG, "ensure discoverable");
if (mBluetoothAdapter.getScanMode() !=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent
.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity
(discoverableIntent);
}
}

/**
* Sends a message.
* @param message A string of text to send.
*/

private void sendMessage(String message) {
// Check that we're actually connected before trying anything
if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
return;
}

// Check that there's actually something to send
if (message.length() > 0) {
// Get the message bytes and tell the BluetoothChatService to write
byte[] send = message.getBytes();
mChatService
.write(send);

// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer
.setLength(0);
mOutEditText
.setText(mOutStringBuffer);
}
}

// The action listener for the EditText widget, to listen for the return key
private TextView.OnEditorActionListener mWriteListener =
new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
// If the action is a key-up event on the return key, send the message
if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
String message = view.getText().toString();
sendMessage
(message);
}
if(D) Log.i(TAG, "END onEditorAction");
return true;
}
};

private final void setStatus(int resId) {
final ActionBar actionBar = getActionBar();
actionBar
.setSubtitle(resId);
}

private final void setStatus(CharSequence subTitle) {
final ActionBar actionBar = getActionBar();
actionBar
.setSubtitle(subTitle);
}

// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
setStatus
(getString(R.string.title_connected_to, mConnectedDeviceName));
mConversationArrayAdapter
.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
setStatus
(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
setStatus
(R.string.title_not_connected);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter
.add("Me: " + writeMessage);
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
mConversationArrayAdapter
.add(mConnectedDeviceName+": " + readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName
= msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};

public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(D) Log.d(TAG, "onActivityResult " + resultCode);
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice
(data, true);
}
break;
case REQUEST_CONNECT_DEVICE_INSECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice
(data, false);
}
break;
case REQUEST_ENABLE_BT:
// When the request to enable Bluetooth returns
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
setupChat
();
} else {
// User did not enable Bluetooth or an error occurred
Log.d(TAG, "BT not enabled");
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish
();
}
}
}

private void connectDevice(Intent data, boolean secure) {
// Get the device MAC address
String address = data.getExtras()
.getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mChatService
.connect(device, secure);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater
.inflate(R.menu.option_menu, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent serverIntent = null;
switch (item.getItemId()) {
case R.id.secure_connect_scan:
// Launch the DeviceListActivity to see devices and do scan
serverIntent
= new Intent(this, DeviceListActivity.class);
startActivityForResult
(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
return true;
case R.id.insecure_connect_scan:
// Launch the DeviceListActivity to see devices and do scan
serverIntent
= new Intent(this, DeviceListActivity.class);
startActivityForResult
(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
return true;
case R.id.discoverable:
// Ensure this device is discoverable by others
ensureDiscoverable
();
return true;
}
return false;
}

}

BluetoothChatServices

/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package com.example.android.BluetoothChat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
* This class does all the work for setting up and managing Bluetooth
* connections with other devices. It has a thread that listens for
* incoming connections, a thread for connecting with a device, and a
* thread for performing data transmissions when connected.
*/

public class BluetoothChatService {
// Debugging
private static final String TAG = "BluetoothChatService";
private static final boolean D = true;

// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";

// Unique UUID for this application
private static final UUID MY_UUID_SECURE =
UUID
.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
private static final UUID MY_UUID_INSECURE =
UUID
.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");

// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;

// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device

/**
* Constructor. Prepares a new BluetoothChat session.
* @param context The UI Activity Context
* @param handler A Handler to send messages back to the UI Activity
*/

public BluetoothChatService(Context context, Handler handler) {
mAdapter
= BluetoothAdapter.getDefaultAdapter();
mState
= STATE_NONE;
mHandler
= handler;
}

/**
* Set the current state of the chat connection
* @param state An integer defining the current connection state
*/

private synchronized void setState(int state) {
if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
mState
= state;

// Give the new state to the Handler so the UI Activity can update
mHandler
.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

/**
* Return the current connection state. */

public synchronized int getState() {
return mState;
}

/**
* Start the chat service. Specifically start AcceptThread to begin a
* session in listening (server) mode. Called by the Activity onResume() */

public synchronized void start() {
if (D) Log.d(TAG, "start");

// Cancel any thread attempting to make a connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

setState
(STATE_LISTEN);

// Start the thread to listen on a BluetoothServerSocket
if (mSecureAcceptThread == null) {
mSecureAcceptThread
= new AcceptThread(true);
mSecureAcceptThread
.start();
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread
= new AcceptThread(false);
mInsecureAcceptThread
.start();
}
}

/**
* Start the ConnectThread to initiate a connection to a remote device.
* @param device The BluetoothDevice to connect
* @param secure Socket Security type - Secure (true) , Insecure (false)
*/

public synchronized void connect(BluetoothDevice device, boolean secure) {
if (D) Log.d(TAG, "connect to: " + device);

// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
}

// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

// Start the thread to connect with the given device
mConnectThread
= new ConnectThread(device, secure);
mConnectThread
.start();
setState
(STATE_CONNECTING);
}

/**
* Start the ConnectedThread to begin managing a Bluetooth connection
* @param socket The BluetoothSocket on which the connection was made
* @param device The BluetoothDevice that has been connected
*/

public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device
, final String socketType) {
if (D) Log.d(TAG, "connected, Socket Type:" + socketType);

// Cancel the thread that completed the connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}

// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}

// Cancel the accept thread because we only want to connect to one device
if (mSecureAcceptThread != null) {
mSecureAcceptThread
.cancel();
mSecureAcceptThread
= null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread
.cancel();
mInsecureAcceptThread
= null;
}

// Start the thread to manage the connection and perform transmissions
mConnectedThread
= new ConnectedThread(socket, socketType);
mConnectedThread
.start();

// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle
.putString(BluetoothChat.DEVICE_NAME, device.getName());
msg
.setData(bundle);
mHandler
.sendMessage(msg);

setState
(STATE_CONNECTED);
}

/**
* Stop all threads
*/

public synchronized void stop() {
if (D) Log.d(TAG, "stop");

if (mConnectThread != null) {
mConnectThread
.cancel();
mConnectThread
= null;
}

if (mConnectedThread != null) {
mConnectedThread
.cancel();
mConnectedThread
= null;
}

if (mSecureAcceptThread != null) {
mSecureAcceptThread
.cancel();
mSecureAcceptThread
= null;
}

if (mInsecureAcceptThread != null) {
mInsecureAcceptThread
.cancel();
mInsecureAcceptThread
= null;
}
setState
(STATE_NONE);
}

/**
* Write to the ConnectedThread in an unsynchronized manner
* @param out The bytes to write
* @see ConnectedThread#write(byte[])
*/

public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r
= mConnectedThread;
}
// Perform the write unsynchronized
r
.write(out);
}

/**
* Indicate that the connection attempt failed and notify the UI Activity.
*/

private void connectionFailed() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle
.putString(BluetoothChat.TOAST, "Unable to connect device");
msg
.setData(bundle);
mHandler
.sendMessage(msg);

// Start the service over to restart listening mode
BluetoothChatService.this.start();
}

/**
* Indicate that the connection was lost and notify the UI Activity.
*/

private void connectionLost() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle
.putString(BluetoothChat.TOAST, "Device connection was lost");
msg
.setData(bundle);
mHandler
.sendMessage(msg);

// Start the service over to restart listening mode
BluetoothChatService.this.start();
}

/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until cancelled).
*/

private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;

public AcceptThread(boolean secure) {
BluetoothServerSocket tmp = null;
mSocketType
= secure ? "Secure":"Insecure";

// Create a new listening server socket
try {
if (secure) {
tmp
= mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE
);
} else {
tmp
= mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE
, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket
= tmp;
}

public void run() {
if (D) Log.d(TAG, "Socket Type: " + mSocketType +
"BEGIN mAcceptThread" + this);
setName
("AcceptThread" + mSocketType);

BluetoothSocket socket = null;

// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket
= mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}

// If a connection was accepted
if (socket != null) {
synchronized (BluetoothChatService.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected
(socket, socket.getRemoteDevice(),
mSocketType
);
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket
.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);

}

public void cancel() {
if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
try {
mmServerSocket
.close();
} catch (IOException e) {
Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
}
}
}


/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/

private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;

public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice
= device;
BluetoothSocket tmp = null;
mSocketType
= secure ? "Secure" : "Insecure";

// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp
= device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE
);
} else {
tmp
= device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE
);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket
= tmp;
}

public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName
("ConnectThread" + mSocketType);

// Always cancel discovery because it will slow down a connection
mAdapter
.cancelDiscovery();

// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket
.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket
.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType +
" socket during connection failure", e2);
}
connectionFailed
();
return;
}

// Reset the ConnectThread because we're done
synchronized (BluetoothChatService.this) {
mConnectThread
= null;
}

// Start the connected thread
connected
(mmSocket, mmDevice, mSocketType);
}

public void cancel() {
try {
mmSocket
.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}

/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/

private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;

public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket
= socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;

// Get the BluetoothSocket input and output streams
try {
tmpIn
= socket.getInputStream();
tmpOut
= socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}

mmInStream
= tmpIn;
mmOutStream
= tmpOut;
}

public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;

// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes
= mmInStream.read(buffer);

// Send the obtained bytes to the UI Activity
mHandler
.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost
();
// Start the service over to restart listening mode
BluetoothChatService.this.start();
break;
}
}
}

/**
* Write to the connected OutStream.
* @param buffer The bytes to write
*/

public void write(byte[] buffer) {
try {
mmOutStream
.write(buffer);

// Share the sent message back to the UI Activity
mHandler
.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}

public void cancel() {
try {
mmSocket
.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}

Device List Activity

/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package com.example.android.BluetoothChat;

import java.util.Set;

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.util.Log;
import android.view.View;
import android.view.Window;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

/**
* This Activity appears as a dialog. It lists any paired devices and
* devices detected in the area after discovery. When a device is chosen
* by the user, the MAC address of the device is sent back to the parent
* Activity in the result Intent.
*/

public class DeviceListActivity extends Activity {
// Debugging
private static final String TAG = "DeviceListActivity";
private static final boolean D = true;

// Return Intent extra
public static String EXTRA_DEVICE_ADDRESS = "device_address";

// Member fields
private BluetoothAdapter mBtAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
private ArrayAdapter<String> mNewDevicesArrayAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Setup the window
requestWindowFeature
(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView
(R.layout.device_list);

// Set result CANCELED in case the user backs out
setResult
(Activity.RESULT_CANCELED);

// Initialize the button to perform device discovery
Button scanButton = (Button) findViewById(R.id.button_scan);
scanButton
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery
();
v
.setVisibility(View.GONE);
}
});

// Initialize array adapters. One for already paired devices and
// one for newly discovered devices
mPairedDevicesArrayAdapter
= new ArrayAdapter<String>(this, R.layout.device_name);
mNewDevicesArrayAdapter
= new ArrayAdapter<String>(this, R.layout.device_name);

// Find and set up the ListView for paired devices
ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
pairedListView
.setAdapter(mPairedDevicesArrayAdapter);
pairedListView
.setOnItemClickListener(mDeviceClickListener);

// Find and set up the ListView for newly discovered devices
ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
newDevicesListView
.setAdapter(mNewDevicesArrayAdapter);
newDevicesListView
.setOnItemClickListener(mDeviceClickListener);

// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);

// Register for broadcasts when discovery has finished
filter
= new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);

// Get the local Bluetooth adapter
mBtAdapter
= BluetoothAdapter.getDefaultAdapter();

// Get a set of currently paired devices
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

// If there are paired devices, add each one to the ArrayAdapter
if (pairedDevices.size() > 0) {
findViewById
(R.id.title_paired_devices).setVisibility(View.VISIBLE);
for (BluetoothDevice device : pairedDevices) {
mPairedDevicesArrayAdapter
.add(device.getName() + "\n" + device.getAddress());
}
} else {
String noDevices = getResources().getText(R.string.none_paired).toString();
mPairedDevicesArrayAdapter
.add(noDevices);
}
}

@Override
protected void onDestroy() {
super.onDestroy();

// Make sure we're not doing discovery anymore
if (mBtAdapter != null) {
mBtAdapter
.cancelDiscovery();
}

// Unregister broadcast listeners
this.unregisterReceiver(mReceiver);
}

/**
* Start device discover with the BluetoothAdapter
*/

private void doDiscovery() {
if (D) Log.d(TAG, "doDiscovery()");

// Indicate scanning in the title
setProgressBarIndeterminateVisibility
(true);
setTitle
(R.string.scanning);

// Turn on sub-title for new devices
findViewById
(R.id.title_new_devices).setVisibility(View.VISIBLE);

// If we're already discovering, stop it
if (mBtAdapter.isDiscovering()) {
mBtAdapter
.cancelDiscovery();
}

// Request discover from BluetoothAdapter
mBtAdapter
.startDiscovery();
}

// The on-click listener for all devices in the ListViews
private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView av, View v, int arg2, long arg3) {
// Cancel discovery because it's costly and we're about to connect
mBtAdapter
.cancelDiscovery();

// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
String address = info.substring(info.length() - 17);

// Create the result Intent and include the MAC address
Intent intent = new Intent();
intent
.putExtra(EXTRA_DEVICE_ADDRESS, address);

// Set result and finish this Activity
setResult
(Activity.RESULT_OK, intent);
finish
();
}
};

// The BroadcastReceiver that 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) {
mNewDevicesArrayAdapter
.add(device.getName() + "\n" + device.getAddress());
}
// When discovery is finished, change the Activity title
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setProgressBarIndeterminateVisibility
(false);
setTitle
(R.string.select_device);
if (mNewDevicesArrayAdapter.getCount() == 0) {
String noDevices = getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter
.add(noDevices);
}
}
}
};

}

Twitter Delicious Facebook Digg Stumbleupon Favorites More