Friday 6 December 2013

 Bluetooth Connection in Android from Matt Bell's blog

Project Structure


Here is the java and xml code from Matt Bell's blog adapted to send data only:

[code]--------------------------------------------------------------------------------------

package here
imports here

public class BluetoothTest extends Activity
{
    TextView myLabel;
    EditText myTextbox;
    BluetoothAdapter mBluetoothAdapter;
    BluetoothSocket mmSocket;
    BluetoothDevice mmDevice;
   
    OutputStream mmOutputStream;
   

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
      
        setContentView(R.layout.activity_main); // need a activity_main layout XML file
// with these objects below in it (buttons, labels etc...):
      
        Button openButton = (Button) findViewById(R.id.open);
        Button sendButton = (Button) findViewById(R.id.send);
        Button closeButton = (Button) findViewById(R.id.close);
        myLabel = (TextView) findViewById(R.id.label);
        myTextbox = (EditText) findViewById(R.id.entry);

        // Open BT connection Button
        openButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                try
                {
                    findBT();
                    openBT();
                } catch (IOException ex)
                {
                }
            }
        });

        // Send Button
        sendButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                try
                {
                    sendData();
                } catch (IOException ex)
                {
                }
            }
        });

        // Close button
        closeButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                try
                {
                    closeBT();
                } catch (IOException ex)
                {
                }
            }
        });
    }

    void findBT()
    {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null)
        {
            myLabel.setText("No bluetooth adapter available");
        }

        if (!mBluetoothAdapter.isEnabled())
        {
            Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBluetooth, 0);
        }

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0)
        {
            for (BluetoothDevice device : pairedDevices)
            {
                if (device.getName().equals("linvor"))// change accordingly
                {
                    mmDevice = device;
                    break;
                }
            }
        }
        myLabel.setText("Bluetooth Device Found");
    }

    void openBT() throws IOException
    {
        UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");                                                                                                                                                         

if (mmDevice != null) 
        {
            mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
            mmSocket.connect();
            mmOutputStream = mmSocket.getOutputStream();           

       
        myLabel.setText("Bluetooth Opened");
        }
    }

   

    void sendData() throws IOException
    {
        String msg = myTextbox.getText().toString();
        msg += "\n";
        mmOutputStream.write(msg.getBytes());
        myLabel.setText("Data Sent");
    }

    void closeBT() throws IOException
    {
      
        mmOutputStream.close();
        mmSocket.close();
        myLabel.setText("Bluetooth Closed");
    }
}// end of java code.


XML code: 
Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="your package"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:label="@string/app_name" >
        <activity android:name="BluetoothTest"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="5" android:targetSdkVersion="9"/>
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <supports-screens android:anyDensity="true" />
</manifest>



Layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TextView
        android:id="@+id/label"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Type here:"/>
    <EditText
        android:id="@+id/entry"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@android:drawable/editbox_background"
        android:layout_below="@id/label"/>
    <Button
        android:id="@+id/open"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/entry"
        android:layout_alignParentRight="true"
        android:layout_marginLeft="10dip"
        android:text="Open" />
    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/open"
        android:layout_alignTop="@id/open"
        android:text="Send" />
    <Button
        android:id="@+id/close"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toLeftOf="@id/send"
        android:layout_alignTop="@id/send"
        android:text="Close" />
</RelativeLayout>


Arduino Test Code:
#include <SoftwareSerial.h>

int bluetoothTx = 2;
int bluetoothRx = 3;

SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
const int LED = 10;
char incomingByte = ' ';

void setup()
{
  //Setup usb serial connection to computer
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  //Setup Bluetooth serial connection to android
  bluetooth.begin(115200);
  bluetooth.print("$$$");
  delay(100);
  bluetooth.println("U,9600,N");
  bluetooth.begin(9600);
  Serial.println("Start");
 
}

void loop()
{


  //Read from bluetooth and write to usb serial
  if(bluetooth.available())
  {
    Serial.println("BlueTooth OK");
    char toSend = (char)bluetooth.read();
    Serial.println(toSend);
    incomingByte = toSend;
  }


if (incomingByte == 'l')
{
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
}
 
}


[end code]----------------------------------------------

17 comments:

  1. Only 1 error remains:
    mmDevice = device; // device is red underlined
    Type mismatch: cannot convert from BluetoothDevice to String

    ReplyDelete
  2. for (BluetoothDevice device : pairedDevices)
    {

    ....
    The parameter [device] should be a BluetoothDevice not a String, as in the above. Can you please post some more code so I can see a complete block? Thanks

    ReplyDelete
  3. My goal is relatively simple, except I am new to Java / Eclipse. I am ok on the arduino side; I have a home grown project which simply needs to send an ascii character from Android to Arduino via Bluetooth on pressing a button on my phone app. As you can tell I started by cludgeing bits together for www in hope it will compile.

    Thanks for your enduring help, newbies are infuriating I am sure.

    My email if it might be easier is les(at)wilkipedia.net




    package com.example.onestep;

    import java.io.InputStream;

    import java.io.OutputStream;
    import java.util.Set;
    import java.util.UUID;

    import android.os.Bundle;
    import android.app.Activity;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothSocket;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.view.*;
    import android.widget.*;


    public class MainActivity extends Activity {
    private BluetoothAdapter btAdapter;
    public Button btn1; //
    public Button btn2;
    public EditText etxt1; //



    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    btn1=(Button)findViewById(R.id.bt_on);
    btn2=(Button)findViewById(R.id.bt_off);
    etxt1=(EditText)findViewById(R.id.editText1);

    // btn1.setOnClickListener(new View.OnClickListener() {


    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub HERE IS code for BT on button
    btAdapter=BluetoothAdapter.getDefaultAdapter();

    if(btAdapter.isEnabled()){
    String address = btAdapter.getRemoteDevice(address);
    String address = btAdapter.getAddress();
    String name = btAdapter.getName();
    String statusBT = name +" : "+address;
    BluetoothDevice mmDevice = "";
    etxt1.setText(statusBT);

    // Pairing
    Set pairedDevices = btAdapter
    .getBondedDevices();
    if (pairedDevices.size() > 0)
    {
    for (BluetoothDevice device : pairedDevices)
    {

    if (device.getName().equals("HC-05")) {
    {
    mmDevice = device;
    break;

    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
    BluetoothSocket mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);
    mmSocket.connect();
    OutputStream mmOutputStream = mmSocket.getOutputStream();
    InputStream mmInputStream = mmSocket.getInputStream();



    // Pairing end

    }
    }
    }
    }

    // else{
    // etxt1.setText("BT Adapter not on");
    // String actionStateChanged = BluetoothAdapter.ACTION_STATE_CHANGED;
    // String actionRequestEnabled = BluetoothAdapter.ACTION_REQUEST_ENABLE;
    // IntentFilter filter = new IntentFilter(actionStateChanged);
    // registerREceiver(bluetoothState, filter);
    // startActivityForResult(new Intent(actionRequestEnabled),0);

    }}});

    btn2.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
    // TODO Auto-generated method stub HERE IS code for BT off button
    // btAdapter.disable(); // Every thing crashes with these 3 lines
    // btn2.setVisibility(View.GONE);
    // etxt1.setText("BTooth is off");
    }
    });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
    }

    }


    ReplyDelete
    Replies
    1. Hi Les. I emailed you some code. But I also published it above.

      Delete
  4. Hi Craig,
    It complies and uploads but the app errors.


    12-09 10:44:26.330: E/AndroidRuntime(13997): FATAL EXCEPTION: main
    12-09 10:44:26.330: E/AndroidRuntime(13997): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.lw_blue_2/com.example.lw_blue_2.BluetoothTest}: java.lang.ClassNotFoundException: Didn't find class "com.example.lw_blue_2.BluetoothTest" on path: /data/app/com.example.lw_blue_2-2.apk
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2299)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread.access$700(ActivityThread.java:154)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.os.Handler.dispatchMessage(Handler.java:99)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.os.Looper.loop(Looper.java:137)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread.main(ActivityThread.java:5297)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at java.lang.reflect.Method.invokeNative(Native Method)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at java.lang.reflect.Method.invoke(Method.java:511)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at dalvik.system.NativeStart.main(Native Method)
    12-09 10:44:26.330: E/AndroidRuntime(13997): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.lw_blue_2.BluetoothTest" on path: /data/app/com.example.lw_blue_2-2.apk
    12-09 10:44:26.330: E/AndroidRuntime(13997): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:65)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.Instrumentation.newActivity(Instrumentation.java:1071)
    12-09 10:44:26.330: E/AndroidRuntime(13997): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2166)
    12-09 10:44:26.330: E/AndroidRuntime(13997): ... 11 more


    Did not get your direct email last time best use les at wilkipedia.net

    If you ever come out to Thailand I owe you a beer.
    Many Thanks Les

    ReplyDelete
  5. I have renamed in xml file as per my project name:-















    ReplyDelete
    Replies
    1. Hello Again, for some reason my emails went to
      wikipedia.net.net


      I tested the code I posted earlier and it connects to BT and sends data with arduino using my Google Nexus 7 tablet.
      Did you still get all those error messages when you changed the XML ?

      Cheers

      Craig

      PS Thanks for the offer of a beer :)

      We all need help starting out. I got lots of help and still do. I find Stack Overflow particularly good for java, except they can be shirty with newbies. It's not as friendly as the Arduino forum.

      Delete
  6. Hi Craig,

    Some progress, I have the app now not crashing on my galaxy, it took some twiddling to the manifest file, I noticed that my eclipse generated raw manifest file was differing from yours so I experimented. At foot I will include my version. The main java file is exactly as you provided, other than I changed my bluetooth device name.

    The app sadly does not send any characters from galaxy to the arduino.
    I presume there is no more one needs to do when using the app other than: click Open, enter an ascii string and click Send. Sadly nothing appears at the other end.


    I know also that another android / arduino testing app called ArduDroid works fine for me and it sends ascii characters between galaxy and arduino ok. Which confirms that pairing, modems, arduino can all talk together ok. ( ArduDroid will not make his android code public sadly, it is quite fun to play with )

    My diagnosis now: It appears most probable that I still have a problem on the android side, it could also be possible the arduino is not displaying what is being sent, but I feel that is less likely.

    I have one idea to eliminate fault on arduino side and that is to loan a friends oscilloscope and monitor the btooth modem Tx pin to see if rs232 is appearing.
    I will do this but it will take a while to arrange.

    Else if you have any suggestions, gratefully received.
    Thanks
    Les

    Manifest file below





















    ReplyDelete
  7. Hi Craig,

    So that you know what I am aiming at with my project.

    I am a keen amateur photographer. My photo gallery is at wilkipedia.net

    I enjoy taking macro photographs and use a technique which is called focus stitching, this involves taking say 30 photographs of an insect, with each shot moved slightly along its body, so as to have the whole insect in focus by joining all the shots together later in some focus stitching software.

    To automate this process I have built an arduino project which controls a stepper motor which moves the camera millimeters at a time along a rail and will automatically take my shots for me once it is setup, the shots are then better as they are very equidistant if it is done by a stepper motor.
    I now have the whole Arduino side working ok and the icing on the cake is to have mobile phone control of the stepper rail.

    Your assistance has been invaluable in saving time and making progress, I hope my brief summary explains what I am up to.

    Thanks

    ReplyDelete
  8. Hi Craig,

    Have just established that when I press open on the android app it does not switch on Bluetooth services on my samsung phone.


    Looking at this bit of code:
    void findBT()
    {
    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null)
    {
    myLabel.setText("No bluetooth adapter available");
    }

    if (!mBluetoothAdapter.isEnabled())
    {
    Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBluetooth, 0);
    }

    Set pairedDevices = mBluetoothAdapter.getBondedDevices();
    if (pairedDevices.size() > 0)
    {
    for (BluetoothDevice device : pairedDevices)
    {
    if (device.getName().equals("HC-05"))// change accordingly
    {
    mmDevice = device;
    break;
    }
    }
    }
    myLabel.setText("Bluetooth Device Found");
    }

    I am surprised that I never see message

    myLabel.setText("No bluetooth adapter available");
    nor
    myLabel.setText("Bluetooth Device Found");

    Rgds
    Les

    ReplyDelete
    Replies
    1. Hi Les,

      I send an email about a correction to the code above and some arduino code. Corrections and Arduino code also posted on this page. Android Java correction was put conditional into openBT() method:

      void openBT() throws IOException

      {

      UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

      if (mmDevice != null) //conditional only do if NOT null

      {

      mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);

      mmSocket.connect();

      mmOutputStream = mmSocket.getOutputStream();



      myLabel.setText("Bluetooth Opened");

      }// end of !null

      Delete
  9. Hi Craig,

    I haven't received your email please can you send again to les at wilkipedia.net

    Thanks

    ReplyDelete
  10. Hi Craig,

    After adding these lines there is no difference.

    It doesn't report "Bluetooth opened"

    Also Bluetooth never gets turned on on the Galaxy phone, if I force and I enable BTooth to be on, it still makes no difference.

    These lines were added
    void openBT() throws IOException

    {

    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

    if (mmDevice != null) //conditional only do if NOT null

    {

    mmSocket = mmDevice.createRfcommSocketToServiceRecord(uuid);

    mmSocket.connect();

    mmOutputStream = mmSocket.getOutputStream();



    myLabel.setText("Bluetooth Opened");

    }// end of !null

    Rgds
    Les

    ReplyDelete
    Replies
    1. Hi Les, I did this:

      1. Start with no BT app running on phone
      2. turned BT off on my Nexus
      3. Run app on Eclipse ADB USB bridge
      4. App running on phone
      5. press open, system message = "app wants to turn on BT deny / allow"
      6. allow
      7. bt app message = "bt device found"
      8. press open again
      9. app message bt opened
      10. type a byte, press send, app says "data sent", data is printed on arduino terminal.

      and it worked. Please try that sequence of events.
      Cheers Craig

      Delete
    2. Hi les, can't send to les@wikipedia.net don'y know why.

      PostMaster says:

      SMTP error from remote server after RCPT command:
      host mchenry.wikimedia.org[208.80.152.186]:
      550 Address les@wikipedia.net does not exist

      cheers

      Craig

      Delete
  11. les@wilkipedia.net there is an L in there my surname is Wilk so I kyboshed a known brand.

    Thanks

    ReplyDelete