Xamarin Form Android Bluetooth Service discovery failed - android

I have an app written in Xamarin Form that connects to a Bluetooth device (not LE).
The code for Bluetooth is written in a DepencedyService.
Some users (minus of 0.1 % ) have said that they get this message : "OS/Service discovery failed"
The function that displays the message is:
public bool OpenSocket(string xxxDevice)
{
bool rVal = false;
try
{
device = (from bd in adapter.BondedDevices
where bd.Address == xxxDevice
select bd).FirstOrDefault();
if (device == null)
return false;
_socket = device.CreateRfcommSocketToServiceRecord(UUID.FromString("00001101-0000-1000-8000-00805f9b34fb"));
_socket.Connect();
rVal = true;
}
catch (System.Exception ex)
{
MessagingCenter.Send<BTCode, string>(this, "Bluetooth", "OS/" + ex.Message);
}
return rVal;
}
Can anyone tell me how to fix this?

Related

bluetooth error no advertisable device

#! /usr/bin/python
import bluetooth
import uuid
server_socket = bluetooth.BluetoothSocket( bluetooth.RFCOMM )
port = 1
server_socket.bind(("",port))
server_socket.listen(1)
uuID = ##generated uuid
bluetooth.advertise_service( server_socket, "test", service_id=uuID )
client_socket, client_address = server_socket.accept()
print(client_socket)
print(client_address)
If anyone could help with this, that would be great. I've tried going through the instructions listed here about 5 times: Python code for Bluetooth throws error after I had to reset the adapter
I keep getting an error saying "bluetooth.btcommon.BluetoothError: error no advertisable device" The line number points to the advertise_service line, and it does so whether or not I add the additional parameters as shown in the example in the pybluez github page, or bind the port to bluetooth.PORT_ANY
The method being called is here:
def advertise_service (sock, name, service_id = "", service_classes = [], \
profiles = [], provider = "", description = "", protocols = []):
if service_id != "" and not is_valid_uuid (service_id):
raise ValueError ("invalid UUID specified for service_id")
for uuid in service_classes:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in service_classes")
for uuid, version in profiles:
if not is_valid_uuid (uuid) or version < 0 or version > 0xFFFF:
raise ValueError ("Invalid Profile Descriptor")
for uuid in protocols:
if not is_valid_uuid (uuid):
raise ValueError ("invalid UUID specified in protocols")
try:
_bt.sdp_advertise_service (sock._sock, name, service_id, \
service_classes, profiles, provider, description, \
protocols)
except _bt.error as e:
raise BluetoothError (str (e))
I'm can't print off the client information if I don't advertise, and get a null pointer exception on the android side, so I figure it's necessary, but can't get past this error if I do advertise.
This is the smallest amount of code I can have to get this error. Like I mentioned, not advertising results in no error, but I can't print off client information on the connect (the android side can't find the pi).
If you do know of a way to do this without that portion, here's the android code:
Set<BluetoothDevice> pairedDevices = BTAdapter.getBondedDevices();
TextView textShowConnected = (TextView) findViewById(R.id.textShowConnected);
if (pairedDevices.size() > 0)
{
for (BluetoothDevice device : pairedDevices)
{
if(device.getName().toString().equals("Pi"))
{
textShowConnected.setText("Found the Pi. Address is "+device.getAddress());
TextView textShowConnectedSocket = (TextView) findViewById(R.id.textShowConnectedSocket);
//textShowConnectedSocket.setText("uuid is: "+device.getUuids()[0].getUuid().toString());
try
{
BluetoothSocket connection = device.createRfcommSocketToServiceRecord(device.getUuids()[0].getUuid());
//BluetoothSocket connection = device.createInsecureRfcommSocketToServiceRecord(device.getUuids()[0].getUuid());
connection.connect();
if(connection.isConnected())
{
textShowConnected.setText("Is connected from second.");
textShowConnectedSocket.setText("Is conencted to: "+connection.getRemoteDevice().getName().toString());
textShowPlace.setText("Is connected to: "+connection.getRemoteDevice().getAddress().toString());
}
else
{
textShowConnected.setText("No connection.");
textShowConnectedSocket.setText("No connection.");
textShowPlace.setText("No connection.");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
//DeviceItem newDevice = new DeviceItem(device.getName(), device.getAddress(), "false");
//deviceItemList.add(newDevice);
}
}
}
My most recent Java side attempt (just in case the pi side was fine):
for (BluetoothDevice device : pairedDevices)
{
if(device.getName().toString().equals("Pi"))
{
textShowConnected.setText("Found the Pi. Address is "+device.getAddress());
TextView textShowConnectedSocket = (TextView) findViewById(R.id.textShowConnectedSocket);
TextView textShowPlace = (TextView) findViewById(R.id.textShowPlace);
//textShowConnectedSocket.setText("uuid is: "+device.getUuids()[0].getUuid().toString());
int bt_port_to_connect = 1;
BluetoothSocket deviceSocket = null;
Method m = null;
try {
textShowPlace.setText("created socket");
m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class});
deviceSocket = (BluetoothSocket) m.invoke(device,bt_port_to_connect);
deviceSocket.connect();
if(deviceSocket.isConnected())
{
textShowPlace.setText("is connected");
textShowConnectedSocket.setText("Connected successfully.");
textShowConnected.setText("Connected to: "+deviceSocket.getRemoteDevice().getName().toString());
}
else
{
textShowConnectedSocket.setText("Did not connect.");
}
}
catch (IOException e)
{
textShowPlace.setText("catch statement "+e);
textShowConnectedSocket.setText("No connection.");
}
catch (NoSuchMethodException e)
{
textShowConnected.setText("No such method.");
textShowPlace.setText("catch statement "+e);
}
catch (InvocationTargetException e)
{
textShowPlace.setText("catch statement "+e);
textShowConnectedSocket.setText("No connection.");
}
catch (IllegalAccessException e)
{
textShowPlace.setText("catch statement "+e);
textShowConnectedSocket.setText("No connection.");
}
//device.createRfcommSocketToServiceRecord(uuid);
//device.createInsecureRfcommSocketToServiceRecord(uuid);
}
//DeviceItem newDevice = new DeviceItem(device.getName(), device.getAddress(), "false");
//deviceItemList.add(newDevice);
}
I'd appreciate any help on this with getting a connection going. I'm not sure what's getting messed up here.
Looks like to advertise it just needed: "sudo hciconfig hci0 piscan"
And to connect it needed bluetooth.PORT_ANY from that import, so I'm marking this as answered.
To anyone that finds this because of their own problems with this. You have an answer now. Good luck.

Android - checking if data connection is actually working

I am currently having a one special use case that I am quite confused how to solve.
We have been checking for internet connection with ConnectivityService that has those ConnectivityType.Wifi / ConnectivityType.Mobile with a property if it is connected / connecting. That is all good until you run into following case:
You have data enabled on your phone.
Data connection is connected.
However you don't pay for your data bill so you can't make any data transfers.
(make sure your wifi is turned off while trying this)
I thought that I would simply check as following:
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl); // replace with https://www.google.com if you like
try
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.Timeout = TimeSpan.FromMilliseconds(5000);
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
var task = httpClient.SendAsync(httpRequestMessage);
task.Wait();
if (task.Result.IsSuccessStatusCode)
return true;
else
return false;
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
}
But this comes with a result of a successful status 200 - which makes me really confused as I clearly can't access anything data oriented on my phone.
I suggest you to check connection by attempting to open a socket to a known host - if the connection is successful - you can be sure that you have network access, else you can check the Exception and handle it to show error connection.
public bool ActiveInternetConnectivity() {
try {
// connect to google on port 80, the HTTP port
var socket = new Java.Net.Socket("www.google.com", 80);
// the above would have thrown exception if failed, so we are good
socket.Close();
return true;
} catch (Exception ex) {
// check logcat to see why it failed, you could then catch and handle each exception independently ( time out, host unknown, end of stream, etc.. )
System.Diagnostics.Debug.WriteLine(ex);
// the connection has failed, return false
return false;
}
It's just an idea, codes are not fully tested.
Ended up implementing following solution that seem to be working quite reliably. You can also enforce reachability on the method.
public static NetworkState GetNetworkState(this Context context, bool testReachability = false)
{
var result = NetworkState.NoNetwork;
var connMgr = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);
var activeNetwork = connMgr.ActiveNetworkInfo;
if (activeNetwork == null || !activeNetwork.IsConnectedOrConnecting)
{
connMgr.Dispose();
return NetworkState.NoNetwork;
}
if (activeNetwork.Type == ConnectivityType.Wifi && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.WiFi;
}
else
{
result = NetworkState.WiFi;
}
}
else if (activeNetwork.Type == ConnectivityType.Mobile && activeNetwork.IsConnected)
{
if (testReachability)
{
if (CanReachServer())
result = NetworkState.Mobile;
}
else
{
result = NetworkState.Mobile;
}
}
activeNetwork.Dispose();
connMgr.Dispose();
return result;
}
private static bool CanReachServer()
{
var uri = new Uri(Platform.ApiServerUrl).GetLeftPart(UriPartial.Authority);
var task = Task.Factory.StartNew(() =>
{
try
{
using (URL url = new URL(uri))
{
using (HttpURLConnection urlc = (HttpURLConnection)url.OpenConnection())
{
urlc.SetRequestProperty("User-Agent", "Android Application");
urlc.SetRequestProperty("Connection", "close");
urlc.ConnectTimeout = 6000;
urlc.ReadTimeout = 10000;
urlc.Connect();
bool result = urlc.ResponseCode == HttpStatus.Ok;
urlc.Disconnect();
return result;
}
}
}
catch (Exception ex)
{
Util.Log(string.Format("{0} - {1}", ex.Message, ex.StackTrace));
return false;
}
});
task.Wait();
return task.Result;
}
}

commumicating between windows app and android app

I'm sorry if this is a very general question but I don't know where to start so I'm looking for ideas.
I have a windows app (music score editing) and I'm currently porting it to Andriod which is coming along well.
I would like to add the feature than documents created in the windows app can be sent to the users android tablet. I was wondering, how would I write some kind of listener on Android that the windows side could open a socket or something to and send data across to it, assuming both are on the same local network.
thanks
I think sending files directly over a local network isn't the best approach. You are prone to many user complaints that the sharing isn't working.. and this will mostly be due to their own network configuration issues.
Why not use a service like DropBox to implement file sharing?
Services like DropBox offer simple API that can be used in apps in order to save files into a remote folder, and read files from a remote folder.
This way, users will not have to be in the same network at all.. and most of the heavy-lifting of implementing file sharing will be done by a service that is focused around that.
Addition:
If you don't want to require an account for a separate service like DropBox, consider this approach: Implement a very simple DropBox-like service on your own web server. Make a simple script that will allow users to upload a file to your server anonymously via HTTP. After upload, they will receive a 5 digit id for this file, or some other link they could share. When using this id or link from the 2nd app, the file could be downloaded (again via HTTP). If you delete files automatically from the server after a few hours, you will not run out of space.
You can implement such a service with about 20 lines of PHP code. And the required apps code is extremely simple (since it only relies on HTTP). If you're worried about the costs of a web server, you can get one from about $5/month or even use a free service like Google App Engine (free if your bandwidth+space requirements are low).
Code example for the file upload. Downloading should be simple enough to do alone. Regarding the periodical file delete - the obvious approach is cron but I think it's easy to manage without it. Whenever you accept a new upload (in the PHP script), go over all the downloads and delete old ones.
i wrote a small thing so my windows app can find an instance of my android app running on the local network, here it is. this is the android code first
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import android.os.AsyncTask;
import android.util.Log;
public class TabSyncServer extends AsyncTask<Void, Void, Void> {
ServerSocket mServerSocket = null;
Socket mSocket = null;
DataInputStream mDataInputStream = null;
DataOutputStream mDataOutputStream = null;
#Override
protected void onPreExecute() {
try {
mServerSocket = new ServerSocket(2112);
//System.out.println("Listening :2112");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected Void doInBackground(Void... args) {
byte[] bytebuf = new byte[1024];
while (true) {
try {
mSocket = mServerSocket.accept();
mDataInputStream = new DataInputStream(mSocket.getInputStream());
mDataOutputStream = new DataOutputStream(mSocket.getOutputStream());
Log.d("TabSyncServer", "ip: " + mSocket.getInetAddress());
mDataInputStream.read(bytebuf);
String str = new String(bytebuf, "UTF8");
Log.d("TabSyncServer", "message: " + str);
if(str.contains("Hello Android")) {
Log.d("TabSyncServer", "sending reply");
mDataOutputStream.writeBytes("Hello Windows");
}
//
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (mSocket != null) {
try {
mSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataInputStream != null) {
try {
mDataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (mDataOutputStream != null) {
try {
mDataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
and the windows MFC code
void CMainFrame::OnBrowseMobile() {
CMobileSync* con = new CMobileSync();
CString ipaddr_base;
int my_last_digit;
if(!con->getMyIP(ipaddr_base, my_last_digit)) {
setMobilePath("Can't find local network");
return;
}
for(int i=1 ; i<98 ; i++) {
if(i==my_last_digit)
continue; // don;t check self
CString ipaddr; ipaddr.Format("%s.%d", ipaddr_base, i);
bool res = con->ConnectToHost(ipaddr);
if(res) {
res = con->SendMsg ("Hello Android");
if(res) {
TRACE1("send ok %s\n",ipaddr.GetBuffer());
#define RD_BUF_LEN 80
char buffer[RD_BUF_LEN];
if(con->ListenOnPortBlocking(buffer, RD_BUF_LEN)) {
if(strncmp(buffer, "Hello Windows", 12)==0) {
TRACE1("reply ok %s", buffer);
setMobilePath(ipaddr);
con->CloseConnection ();
return;
}
}
} else {
TRACE("send FAILED\n");
}
}
con->CloseConnection ();
}
setMobilePath("No TabTrax on local network");
}
#include "stdafx.h"
#include <winsock.h>
#include "MobileSync.h"
#define TTPORT 2112
bool CMobileSync::getMyIP(CString& ipaddr_front, int& ipaddr_lastdigit)
{
char szBuffer[1024];
#ifdef WIN32
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
if(::WSAStartup(wVersionRequested, &wsaData) != 0)
return false;
#endif
if(gethostname(szBuffer, sizeof(szBuffer)) == SOCKET_ERROR)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
struct hostent *host = gethostbyname(szBuffer);
if(host == NULL)
{
#ifdef WIN32
WSACleanup();
#endif
return false;
}
//Obtain the computer's IP
unsigned char b1, b2, b3, b4;
b1 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b1;
b2 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b2;
b3 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b3;
b4 = ((struct in_addr *)(host->h_addr))->S_un.S_un_b.s_b4;
ipaddr_front.Format("%d.%d.%d", b1, b2, b3);
ipaddr_lastdigit = b4;
#ifdef WIN32
WSACleanup();
#endif
return true;
}
//CONNECTTOHOST – Connects to a remote host
bool CMobileSync::ConnectToHost(const char* IPAddress)
{
//Start up Winsock…
WSADATA wsadata;
int error = WSAStartup(0x0202, &wsadata);
//Did something happen?
if (error)
return false;
//Did we get the right Winsock version?
if (wsadata.wVersion != 0x0202)
{
WSACleanup(); //Clean up Winsock
return false;
}
//Fill out the information needed to initialize a socket…
SOCKADDR_IN target; //Socket address information
target.sin_family = AF_INET; // address family Internet
target.sin_port = htons (TTPORT); //Port to connect on
target.sin_addr.s_addr = inet_addr (IPAddress); //Target IP
mSocket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); //Create socket
if (mSocket == INVALID_SOCKET)
{
return false; //Couldn't create the socket
}
//Try connecting...
if (connect(mSocket, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR)
{
return false; //Couldn't connect
}
return true; //Success
}
//CLOSECONNECTION – shuts down the socket and closes any connection on it
void CMobileSync::CloseConnection ()
{
//Close the socket if it exists
if (mSocket)
closesocket(mSocket);
mSocket=0;
WSACleanup(); //Clean up Winsock
}
int CMobileSync::SendMsg (char* szpText, int buflen)
{
if(buflen==0)
buflen = strlen(szpText);
int ret = send(mSocket, szpText, buflen, 0);
TRACE1("CMobileSync::SendMsg sent %d bytes\n", ret);
return ret;
}
WSADATA w;
//LISTENONPORT – Listens on a specified port for incoming connections
//or data
bool CMobileSync::ListenOnPortBlocking(char* buffer, int buflen)
{
//Now we can start listening (allowing as many connections as possible to
//be made at the same time using SOMAXCONN). You could specify any
//integer value equal to or lesser than SOMAXCONN instead for custom
//purposes). The function will not //return until a connection request is
//made
// listen(s, SOMAXCONN);
memset(buffer, 0, sizeof(buffer)); //Clear the buffer
int iTimeout = 1600;
setsockopt( mSocket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&iTimeout, sizeof(iTimeout));
//Put the incoming text into our buffer
int ret = recv (mSocket, buffer, buflen-1, 0);
//Don't forget to clean up with CloseConnection()!
if(ret != SOCKET_ERROR)
return true;
int err = WSAGetLastError();
return false;
}
its not tested extensively but it is running
this maybe useful to someone

Android 4.0+ Bluetooth connection error to an embedded device: "Permission Denied"

I have the following setup:
An Android device uses a 'Client' socket to connect to a remote embedded device, The Android application uses the following code snippet to connect to the embedded device.
On the embedded device uses MindTree BT stack, where server serial socket is prepared according to some properties in the device, which the Android application is familiar with, the connection defined on the embedded device, is not secured!!
The combination of both applications works on:
2 LG phones different models (version code < 10 uses the "Normal method")
2 HTC's different models (version code < 10 uses the "Workaround method")
Pantech Tablet (version code < 13 uses the "Workaround method")
Today, I've tried the application on Samsung S3, Motorola MB886, and a Nexus 7...
All resulted in a "Permission Denied" when calling to socket.connect()... (I have the proper permissions in the manifest, otherwise it would not work on the other devices.)
All the new devices I've tested on are version code > 4.0, so I'm wondering:
Does anyone know about any changes in the API?
Perhaps Android 4.0+ forces security?
It seem that the error occur in the Bonding state, since I can see on the embedded program logs...
Any insights?
The code:
public final synchronized int connectToDevice(int connectingMethod)
throws BluetoohConnectionException {
if (socket != null)
throw new BadImplementationException("Error socket is not null!!");
connecting = true;
logInfo("+---+ Connecting to device...");
try {
lastException = null;
lastPacket = null;
if (connectingMethod == BluetoothModule.BT_StandardConnection
|| connectingMethod == BluetoothModule.BT_ConnectionTBD)
try {
socket = fetchBT_Socket_Normal();
connectToSocket(socket);
listenForIncomingSPP_Packets();
onConnetionEstablished();
return BluetoothModule.BT_StandardConnection;
} catch (BluetoohConnectionException e) {
socket = null;
if (connectingMethod == BluetoothModule.BT_StandardConnection) {
throw e;
}
logWarning("Error creating socket!", e);
}
if (connectingMethod == BluetoothModule.BT_ReflectiveConnection
|| connectingMethod == BluetoothModule.BT_ConnectionTBD)
try {
socket = fetchBT_Socket_Reflection(1);
connectToSocket(socket);
listenForIncomingSPP_Packets();
onConnetionEstablished();
return BluetoothModule.BT_ReflectiveConnection;
} catch (BluetoohConnectionException e) {
socket = null;
if (connectingMethod == BluetoothModule.BT_ReflectiveConnection) {
throw e;
}
logWarning("Error creating socket!", e);
}
throw new BluetoohConnectionException("Error creating RFcomm socket for BT Device:" + this
+ "\n BAD connectingMethod==" + connectingMethod);
} finally {
connecting = false;
}
}
protected void onConnetionEstablished() {
logInfo("+---+ Connection established");
}
private synchronized void listenForIncomingSPP_Packets() {
if (socketListeningThread != null)
throw new BadImplementationException("Already lisening on Socket for BT Device" + this);
logInfo("+---+ Listening for incoming packets");
socketListeningThread = new Thread(socketListener, "Packet Listener - " + bluetoothDevice.getName());
socketListeningThread.start();
}
private BluetoothSocket fetchBT_Socket_Normal()
throws BluetoohConnectionException {
try {
logInfo("+---+ Fetching BT RFcomm Socket standard for UUID: " + uuid + "...");
return bluetoothDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
} catch (Exception e) {
throw new BluetoohConnectionException("Error Fetching BT RFcomm Socket!", e);
}
}
private BluetoothSocket fetchBT_Socket_Reflection(int connectionIndex)
throws BluetoohConnectionException {
Method m;
try {
logInfo("+---+ Fetching BT RFcomm Socket workaround index " + connectionIndex + "...");
m = bluetoothDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
return (BluetoothSocket) m.invoke(bluetoothDevice, connectionIndex);
} catch (Exception e) {
throw new BluetoohConnectionException("Error Fetching BT RFcomm Socket!", e);
}
}
private void connectToSocket(BluetoothSocket socket)
throws BluetoohConnectionException {
try {
logInfo("+---+ Connecting to socket...");
socket.connect();
logInfo("+---+ Connected to socket");
} catch (IOException e) {
try {
socket.close();
} catch (IOException e1) {
logError("Error while closing socket", e1);
} finally {
socket = null;
}
throw new BluetoohConnectionException("Error connecting to socket with Device" + this, e);
}
}
After very long long time of investigating the matter I've found one reason for the error... on some Android devices the auto Bluetooth peering is not enabled/allowed.
So, apparently except for two connection method, there are also two Bluetooth adapter enabling method, one would be to throw an intent to ask the system to turn the adapter on, and the other is to call onto the BluetoothAdapter.enable() method, which enables the Bluetooth silently.
The first method, pops a confirmation dialog, and require user interaction while the other does not, and while not showing the Bluetooth enabling confirmation dialog, also the peering confirmation is not shown, which causes the connection error.
Using the first adapter enabling method solves the problem on most of the devices, like the Nexus 7, Samsung S3, and a few others, but on some devices there is still an issue, and I'm not really sure why, but this is much better since many devices are now working with the new implementation.

How to interact between an Android and a running NXT program using Bluetooth

I have modified the Minddroid github Android program to read sensors on a LEGO NXT (wonderful device!). Now I would like to read and write Bluetooth messages to a Mindstorms program running in the NXT.
So that I can run a NXT program and send the results / readings to the Android when the Android asks for them.
I've created a project where the NXT sends data back to my Android device. Here's some code that should work:
This is all the Android side code:
This is a class that I wrote, that will take care of connecting and communicating via bluetooth.
public class Connector {
public static final String TAG = "Connector";
public static final boolean BT_ON = true;
public static final boolean BT_OFF = false;
public BluetoothAdapter bluetoothAdapter;
public BluetoothSocket bluetoothSocket;
public String address;
public Connector(String address) {
this.address = address;
this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public void setBluetooth(boolean state) {
if(state == Connector.BT_ON) {
// Check if bluetooth is off
if(this.bluetoothAdapter.isEnabled() == false)
{
this.bluetoothAdapter.enable();
while(this.bluetoothAdapter.isEnabled() == false) {
}
Log.d(Connector.TAG, "Bluetooth turned on");
}
}
// Check if bluetooth is enabled
else if(state == Connector.BT_OFF) {
// Check if bluetooth is enabled
if(this.bluetoothAdapter.isEnabled() == true)
{
this.bluetoothAdapter.disable();
while(this.bluetoothAdapter.isEnabled() == true) {
}
Log.d(Connector.TAG, "Bluetooth turned off");
}
}
}
public boolean connect() {
boolean connected = false;
BluetoothDevice nxt = this.bluetoothAdapter.getRemoteDevice(this.address);
try {
this.bluetoothSocket = nxt.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
this.bluetoothSocket.connect();
connected = true;
}
catch (IOException e) {
connected = false;
}
return connected;
}
public Integer readMessage() {
Integer message;
if(this.bluetoothSocket!= null) {
try {
InputStreamReader input = new InputStreamReader(this.bluetoothSocket.getInputStream());
message = input.read();
Log.d(Connector.TAG, "Successfully read message");
}
catch (IOException e) {
message = null;
Log.d(Connector.TAG, "Couldn't read message");
}
}
else {
message = null;
Log.d(Connector.TAG, "Couldn't read message");
}
return message;
}
}
In your activity class, you can create a Connector object. In the onCreate() method, you'll have to connect to establish a connection to the NXT like so:
// Establish a bluetooth connection to the NXT
this.connector = new Connector("00:16:53:12:B6:78");
this.connector.setBluetooth(Connector.BT_ON);
this.connector.connect();
Now to read a message from the NXT (an Integer object) you can do it like this:
this.connector.readMessage();
To close the connection:
this.connector.setBluetooth(Connector.BT_OFF);
This is all the NXT side code:
NOTE: Download leJOS for all the code to work (leJOS will allow you to code your NXT in java).
Define these two objects in your main class:
public static DataOutputStream dataOutputStream;
public static NXTConnection bluetoothConnection;
To connect to you phone:
bluetoothConnection = Bluetooth.waitForConnection();
bluetoothConnection.setIOMode(NXTConnection.RAW);
dataOutputStream = bluetoothConnection.openDataOutputStream();
To send data to the phone in form of an Integer object:
dataOutputStream.write(100);
dataOutputStream.flush();
To disconnect run this:
dataOutputStream.close();
bluetoothConnection.close();
I hope this helps.
I was getting slightly confused with the bluetooth commands, but now I see that you need to download leJOS!
I usually try to avoid messing with the firmware on the NXT, but java is a lot easier to deal with!
For anyone that is interested, you can send commands down to the NXT from your android in its native format, although its not as pretty as listed above. There is a great tutorial here:
http://www.robotappstore.com/Knowledge-Base/Programming-LEGO-NXT-Mindstorms/92.html
But if you want to download an app for free, here is one:
http://www.robotappstore.com/Apps/Lego-NXT-Mindstorms-Driver---Android-app.html?x=693A00AA-7F15-46E7-9616-8101068DB58D
There are a bunch more, if you just search around on there too
Hope this helps!

Categories

Resources