This is the simple code where i'll use me Android phone to send the password to the ArduinoMKR1000 over a network which will in turn check your password and unlock the gift. I use UDP sockets. The Arduino code is:
#include <SPI.h>
#include <WiFi101.h>
#include <WiFiUdp.h>
// TODO change this
int status = WL_IDLE_STATUS;
char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "secretPassword"; // your network password (use for WPA, or use
// as key for WEP)
unsigned int localPort = 2390; // local port to listen on
char packetBuffer[255]; // buffer to hold incoming packet
char replyRight[] = "you have your gift!"; // a string to send back
char replyWrong[] = "try again!";
WiFiUDP Udp;
// Array of passwords to choose from, expand it or fetch some words from the
// internet!
const int PasswordArrayLength=5;
String passwords[PasswordArrayLength] = {
"Merry",
"Christmas",
"42", // The meaning of everything must be here!
"Santa",
"HoHo"
};
bool checkPassword(); // Checks for the received password
void openGift(); // Unlocks the gift
void showWarning(); // Locks the gift and displays the warning
const int lockPin = 4;
const int warningLedPin = 5;
String guess; // password guess
void setup() {
// Initialize serial
Serial.begin(9600);
// attempt to connect to WiFi network:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to Wifi: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
// print your WiFi shield's IP address, your phone will connect to this IP Address
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// if you get a connection, report back via serial:
Udp.begin(localPort);
}
void loop() {
// if there's data available, read a packet
int packetSize = Udp.parsePacket();
if (!packetSize)
{
// read the packet into packetBufffer
int len = Udp.read(packetBuffer, 255);
if (len > 0) packetBuffer[len] = 0; // Null terminate the string to avoid data corruption
Serial.println("Entered password:");
Serial.println(packetBuffer);
guess=String(packetBuffer); // Put the char array in a string to compare easily
if (checkPassword())
{
// Open the gift
openGift();
// Send the reply
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(replyRight);
Udp.endPacket();
}
else
{
// Show alert
showWarning();
// Tell the sender to try again
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(replyWrong);
Udp.endPacket();
}
}
}
void openGift()
{
digitalWrite(lockPin,HIGH); // Unlock the gift
digitalWrite(warningLedPin,LOW); // Turn of the warning if it was on
}
void showWarning()
{
digitalWrite(warningLedPin,LOW); // Turn on the warning led
digitalWrite(lockPin,HIGH); // Lock the gift
}
bool checkPassword()
{
for(int i =0; i < PasswordArrayLength; i++)
{
if(guess.equals(passwords[i]))
{
return true;
}
}
return false;
}
while the code of android is:
package com.example.ahmed.udpsender;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Toast;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.regex.Pattern;
public class MainActivity extends AppCompatActivity
private DatagramSocket socket;
private EditText ipEditText;
private EditText portEditText;
private EditText messageEditText;
// Socket operation time out in milliseconds
private static final int TIMEOUT_MILLIS = 2000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
// Get the handles of the text fields to use them in validation later
// NOTE: this must exist after "setContentView(R.layout.activity_main);"
ipEditText = ((EditText) findViewById(R.id.editTextIp));
portEditText = ((EditText) findViewById(R.id.editTextPort));
messageEditText = ((EditText) findViewById(R.id.textAreaMessage));
try {
socket = new DatagramSocket(); // Create a UDP socket
socket.setBroadcast(true); // Enable broadcasts
socket.setSoTimeout(TIMEOUT_MILLIS); // Set timeout for socket operations
} catch (SocketException e) {
showToast(e.getMessage());
}
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSendButtonClick();
}
});
}
#Override
public void onDestroy() {
super.onDestroy();
this.socket.close(); // Destroy the socket when the app closes
}
private void onSendButtonClick() {
final String ipString = ipEditText.getText().toString();
final String portString = portEditText.getText().toString();
boolean ipValidated = validateIp(ipString);
boolean portValidated = validatePort(portString);
if (!ipValidated && !portValidated) {
showToast("Ip and Port are invalid");
} else if (!ipValidated) {
showToast("IP is invalid");
} else if (!portValidated) {
showToast("Port number is invalid");
} else { // Parameters are syntactically correct
Editable editable = messageEditText.getText();
final String message = editable.toString(); // Get the text in the EditText
// Network operations must be started on a separate
// thread other than the UI thread
new Thread() {
public void run() {
if (sendPacket(message, ipString, Short.parseShort(portString))) {
String reply = receivePacket();
showToastOnUiThread(reply);
}
}
}.start();
editable.clear(); // Clear the message edit text
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private boolean validateIp(String ip) {
if (ip.length() == 0) return false;
if (!IP_ADDRESS.matcher(ip).matches()) {
// Show a message
showToast("Please enter a valid IP Address");
return false;
} else {
return true;
}
}
private boolean validatePort(String text) {
if (text.length() == 0) return false;
try {
Short.parseShort(text); // If this succeeds, then it's a valid port
return true;
} catch (NumberFormatException e) {
showToast("A valid port number is between 1 and " + Short.MAX_VALUE);
return false;
}
}
private boolean sendPacket(String message, String ipString, short portNumber) {
byte messageBytes[] = message.getBytes();
if (message.isEmpty()) return false;
try {
// Create the packet containing the message, IP and port number
final DatagramPacket packet = new DatagramPacket(messageBytes, messageBytes.length,
InetAddress.getByName(ipString), portNumber);
socket.send(packet);
// The UDP packet left the pc safely, we don't know if it was received somewhere
return true;
} catch (final UnknownHostException e) {
showToastOnUiThread("Couldn't find host");
return false;
} catch (final IOException e) {
showToastOnUiThread(e.getMessage());
return false; // Something went wrong
}
}
private String receivePacket() {
try {
byte buffer[] = new byte[255];
DatagramPacket p = new DatagramPacket(buffer, buffer.length);
socket.receive(p);
return new String(p.getData()); // Convert the packet to a string and return it
} catch (IOException ignored) {
}
// Nobody replied to the packet, maybe the address didn't exist in the network
return "Nothing received, timeout";
}
// A toast is the tiny message you see on the screen
private void showToastOnUiThread(final String text) {
runOnUiThread(new Runnable() {
#Override
public void run() {
showToast(text);
}
});
}
private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
//--------------------------------------------------------------------------------------
// Regex for validating IP addresses
private static final Pattern IP_ADDRESS
= Pattern.compile(
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9]))");
}
THE PROBLEM IS: when i try to input the password android return toast "Nothing received, timeout" while arduino stop the void loop(). What is the problem? Ps I have conneted arduino and android at the same external hotspot
i have Resolved replace //Send the reply with a brodcast ip: Udp.remoteIP() change in IPAddress ip(255, 255, 255, 255);
Related
Hi Im new to android studio and java and was hoping to read data from arduino to android.
The plan is to have the button widget on my interface to send signal to the arduino and have my flex sensor send info back to the android via bluetooth.
the bluetooth module i have is HC-06 and this code is designed so that the phone sends a '*' to the arduino and it sends a random value back to the android but i would like that random value to be shown on a textbox on my interface. the change is meant to happen on java ofcourse but im not sure how to do it. Please help.
this is my arduino code first
#include <SoftwareSerial.h>
const int RX_PIN = 2;
const int TX_PIN = 3;
SoftwareSerial serial(RX_PIN, TX_PIN);
char commandChar;
void setup ()
{
serial.begin (9600);
andomSeed(analogRead(0))
}
void loop ()
{
if(serial.available())
{
commandChar = serial.read();
switch(commandChar)
{
case '*':
serial.print(random(1000) + "#");
break;
}
}
}
and here is my code done on android studio:
package com.example.ft.myapplication;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
public class MainActivity extends AppCompatActivity {
BluetoothAdapter mBluetoothAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
BluetoothDevice mDevice = null;
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
mDevice = device;
}
}
ConnectThread mConnectThread = new ConnectThread(mDevice);
mConnectThread.start();
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
byte[] writeBuf = (byte[]) msg.obj;
int begin = (int)msg.arg1;
int end = (int)msg.arg2;
switch(msg.what) {
case 1:
String writeMessage = new String(writeBuf);
writeMessage = writeMessage.substring(begin, end);
break;
}
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException connectException) {
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
ConnectedThread mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
String s = "*";
write(s.getBytes());
byte[] buffer = new byte[1024];
int begin = 0;
int bytes = 0;
while (true) {
try {
bytes += mmInStream.read(buffer, bytes, buffer.length - bytes);
for(int i = begin; i < bytes; i++) {
if(buffer[i] == "#".getBytes()[0]) {
mHandler.obtainMessage(1, begin, i, buffer).sendToTarget();
begin = i + 1;
if(i == bytes - 1) {
bytes = 0;
begin = 0;
}
}
}
} catch (IOException e) {
break;
}
}
}
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
}
This question already has answers here:
NetworkOnMainThreadException [duplicate]
(5 answers)
Closed 7 years ago.
On Being a Duplicate: Please note that I have acknowledged other Q&As (Thread UI) but my case is different as I have tried to use the solution but it doesn't work at all instances (as it works for writing but doesn't for reading.
Updated: I know exactly what is going wrong please read the bold My Question part
I'm trying to make an Android Socket Client that connects to a Java server via WiFi.The final client will send and receive commands and logs as there will be a textbox that user can write SQL commands in it and by hitting a button command will be sent from the app to the Desktop server and show the log in another textbox.
so far I have been trying to use This Answer from another question to make that Client, and adding following lines in the TCP client.
Scanner in = new Scanner(socket.getInputStream());//in doInBackground
//also changed send method a little
public String send(String command)
{
if ( connected ){
out.println(command);
out.flush();
String back = in.nextLine().toString();
return back;
}
return "not Connected";
}
The connection is made successfully and the send method does send the command while server receives it.but the String that server writes back throw the mentioned exception in the title despite the fact that I am using the AsyncTask.
My Question
Why Scanner throws this exception while PrintWriter works correctly ?
Main Activity
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
EditText serverIP, servMsg;
String ip, serverOut;
Button connectBtn;
TcpClient tcpClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
serverIP = (EditText) findViewById(R.id.serverIP);
connectBtn = (Button) findViewById(R.id.connectBtn);
servMsg = (EditText) findViewById(R.id.servMsg);
}
public void onConnectBtn(View view){
try{
ip = serverIP.getText().toString();
tcpClient = new TcpClient();
tcpClient.connect(getApplicationContext(), ip, 8082);
serverOut = tcpClient.send("HELLO FROM cat:123");
servMsg.setText(serverOut);
tcpClient.disconnect(getApplicationContext());
}
catch (Exception e){
Toast.makeText(getApplicationContext(),
"Exception on runnning thread: " + e.getMessage().toString(), Toast.LENGTH_LONG).show();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
TCP Client
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
public class TcpClient {
private static final String TAG = TcpClient.class.getSimpleName();
private Socket socket;
private PrintWriter out;
private Scanner in;
private boolean connected;
public TcpClient() {
socket = null;
out = null;
connected = false;
}
public void connect(Context context, String host, int port) {
new ConnectTask(context).execute(host, String.valueOf(port));
}
private class ConnectTask extends AsyncTask<String, Void, Void> {
private Context context;
public ConnectTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
showToast(context, "Connecting..");
super.onPreExecute();
}
#Override
protected void onPostExecute(Void result) {
if (connected) {
showToast(context, "Connection successful");
}
super.onPostExecute(result);
}
private String host;
private int port;
#Override
protected Void doInBackground(String... params) {
try {
String host = params[0];
int port = Integer.parseInt(params[1]);
socket = new Socket(host, port);
out = new PrintWriter(socket.getOutputStream(), true);
in = new Scanner(socket.getInputStream());
} catch (UnknownHostException e) {
showToast(context, "Don't know about host: " + host + ":" + port);
Log.e(TAG, e.getMessage());
} catch (IOException e) {
showToast(context, "Couldn't get I/O for the connection to: " + host + ":" + port);
Log.e(TAG, e.getMessage());
}
connected = true;
return null;
}
}
public void disconnect(Context context) {
if (connected) {
try {
out.close();
socket.close();
connected = false;
} catch (IOException e) {
showToast(context, "Couldn't get I/O for the connection");
Log.e(TAG, e.getMessage());
}
}
}
/**
* Send command to a Pure Data audio engine.
*/
public String send(String command)
{
if ( connected ){
out.println(command);
out.flush();
String back = in.nextLine().toString();
return back;
}
return "not Connected";
}
private void showToast(final Context context, final String message) {
new Handler(context.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
});
}
}
Also the Layout right now consist of two TextEdits one in which user types IP of the computer(which I checked with correct IPs) and the second one is going to show Server response.
I believe you are not "flushing", which is essentially forcing the buffer to empty out its contents. Please take a look at this working chat server/client code that uses TCP/IP. On a side note, I would recommend not extending ActionBarActivity because it is deprecated (Google says they will move away from it and won't be supporting it soon). Please see 3rd link.
ChatServer.java
ChatClient.java
ActionBar Activity deprecation
I have a Handler called 'bluetoothIn' and I want to pass it to a separate looper using the HandlerThread class which will provide the looper. However I need to post the results back to the UI thread from 'handleMessage(Message msg)' since I can't modify UI elements from threads other than the main thread.
Here is my code :
package com.uniproj.senseplate;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
#SuppressWarnings("unused")
public class MainActivity extends Activity {
Button btnscan;
TextView txtArduino, txtString, txtStringLength, calorie;
Handler bluetoothIn;
final int handlerState = 0; //used to identify handler message
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket; //= null;
private StringBuilder recDataString = new StringBuilder();
private ConnectedThread mConnectedThread;
// SPP UUID service - this should work for most devices
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// String for MAC address
private static String address;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Link the buttons and textViews to respective views
btnscan = (Button) findViewById(R.id.scanBtn);
txtString = (TextView) findViewById(R.id.txtString);
txtStringLength = (TextView) findViewById(R.id.testView1);
bluetoothIn = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == handlerState) {
String readMessage = (String) msg.obj;
recDataString.append(readMessage);
int endOfLineIndex = recDataString.indexOf("~");
if (endOfLineIndex > 0) {
String dataInPrint = recDataString.substring(0, endOfLineIndex);
txtString.setText("Data Received = " + dataInPrint);
int dataLength = dataInPrint.length();
txtStringLength.setText("String Length = " + String.valueOf(dataLength));
if (recDataString.charAt(0) == '#')
{
//get sensor value from string between indices 1-20
String weight = recDataString.substring(1, 20);
//update the textviews with sensor values
calorie.setText(weight + "kg");
}
recDataString.delete(0, recDataString.length());
// strIncom =" ";
dataInPrint = " ";
}
}
}
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
// Set up onClick listeners for button to scan for data
btnscan.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mConnectedThread.write("0");
}
});
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//creates secure outgoing connecetion with BT device using UUID
}
#Override
public void onResume() {
super.onResume();
//Get MAC address from DeviceListActivity via intent
Intent intent = getIntent();
//Get the MAC address from the DeviceListActivty via EXTRA
address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
//create device and set the MAC address
BluetoothDevice device = btAdapter.getRemoteDevice(address);
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
}
// Establish the Bluetooth socket connection.
try
{
btSocket.connect();
} catch (IOException e) {
try
{
btSocket.close();
} catch (IOException e2)
{
//insert code to deal with this
}
}
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
//I send a character when resuming.beginning transmission to check device is connected
//If it is not an exception will be thrown in the write method and finish() will be called
mConnectedThread.write("x");
}
#Override
public void onPause()
{
super.onPause();
try
{
//Don't leave Bluetooth sockets open when leaving activity
btSocket.close();
} catch (IOException e2) {
//insert code to deal with this
}
}
//Checks that the Android device Bluetooth is available and prompts to be turned on if off
private void checkBTState() {
if(btAdapter==null) {
Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toast.LENGTH_LONG).show();
} else {
if (btAdapter.isEnabled()) {
} else {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
//create new class for connect thread
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
btSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer);
bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
//write method
public void write(String input) {
byte[] msgBuffer = input.getBytes();//converts entered String into bytes
try {
mmOutStream.write(msgBuffer);//write bytes over BT connection via outstream
} catch (IOException e) {
//if you cannot write, close the application
Toast.makeText(getBaseContext(), "Connection Failed", Toast.LENGTH_LONG).show();
finish();
}
}
public class BluetoothInHandler extends Handler{
private Looper sLooper = null;
private Handler mWorkerThreadHandler;
final int handlerState = 0; //used to identify handler message
protected class WorkerArgs {
Handler handler;
String input;
String output;
}
public BluetoothInHandler() {
super();
synchronized (BluetoothInHandler.class) {
if (sLooper == null) {
HandlerThread thread = new HandlerThread("AsyncWorker");
thread.start();
sLooper = thread.getLooper();
}
}
mWorkerThreadHandler = new WorkerHandler(sLooper);
}
#Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
String readMessage = args.output;
//your job;
} else {
super.handleMessage(msg);
}
}
public void write(String input) {
WorkerArgs args = new WorkerArgs();
args.handler = this;
args.input = input;
Message message = mWorkerThreadHandler.obtainMessage(handlerState);
message.obj = args;
mWorkerThreadHandler.sendMessage(message);
}
protected class WorkerHandler extends Handler {
public WorkerHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
if (msg.what == handlerState) {
WorkerArgs args = (WorkerArgs) msg.obj;
//the code here run in a thread, not in the ui thread
//do your job like:
byte[] bytes = mmInStream.read(buffer);
args.output = new String(bytes);
Message message = args.handler.obtainMessage(handlerState);
message.obj = args;
message.sendToTarget();
}
}
}
}
}//ConnectedThread End
}
runOnUi might be a good choice for this
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do whatever you need to do on the UI here
}
});
Sorry, I made a mistake. I think the error is causing by the code bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget();
change to
bluetoothIn.obtainMessage(handlerState, bytes, -1, new String(buffer)).sendToTarget();
Remove the code I wrote. It is no use.
I make a client in Java, and make some test on Eclipse IDE and work perfectly, on localhost, external server, etc.
When I export the code to android, it doesn't work, the server don't receive nothing ...
Class code:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
/**
* Jose Manuel R---- ----
* Java version 2.0
*/
public class ClienteTCP {
private CharSequence TCP_HOST = "localhost";
private int TCP_PORT = 5000;
volatile private CharSequence SSID, PASS, SERVER_IP;
volatile private int SERVER_PORT;
final private String START = "START";
// Constructor vacio
public ClienteTCP( ) {
}
// Constructor con argumentos
public ClienteTCP(CharSequence tcp_host, int tcp_port, CharSequence ssid, CharSequence pass, CharSequence ip, int port) {
this.TCP_HOST = tcp_host;
this.TCP_PORT = tcp_port;
this.SSID = ssid;
this.PASS = pass;
this.SERVER_PORT = port;
this.SERVER_IP = ip;
}
// CONF METHODS
public void setServerTCPConf(CharSequence host, int port) {
setTCP_HOST(host);
setTCP_PORT(port);
}
public void setApConf(CharSequence ssid, CharSequence pass) {
setSSID(ssid);
setPASS(pass);
}
public void setServerConf(CharSequence ip, int port) {
setSERVER_IP(ip);
setSERVER_PORT(port);
}
// PUBLIC METHODS
public String configureMC() {
sendMessage( createMessage("AP="+SSID.toString()+","+PASS.toString().toString()) );
sendMessage( createMessage("SERVER="+SERVER_IP.toString()+","+SERVER_PORT) );
return sendMessage( createMessage(START) );
}
public String sendMessage(String msg) {
String msgRec = null;
Socket s;
try {
s = new Socket(TCP_HOST.toString(), TCP_PORT);
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
writer.write(msg, 0, msg.length());
writer.flush();
msgRec = reader.readLine();
reader.close();
writer.close();
s.close();
} catch (IOException e) {
android.util.Log.d("log", e.getMessage());
// e.printStackTrace();
}
return msgRec;
}
// PRIVATE METHODS
private String createMessage(String msg) {
char _AF = ((char)175);
char _FA = (char)250;
return (_AF+msg+_FA);
}
}
MainActivity:
/*
Jose Manuel adad adsasd
TCP client for Android
v1.2-alpha
*/
import android.os.StrictMode;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.net.Socket;
public class MainActivity extends ActionBarActivity {
private volatile EditText debugText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Button button = (Button) findViewById(R.id.SEND);
EditText ssid = (EditText) findViewById(R.id.textSsid);
EditText pass = (EditText) findViewById(R.id.textPass);
debugText = (EditText) findViewById(R.id.debugText);
debugText.setText("Version 1-alpha");
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Do something in response to button click
demo();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void demo() {
ClienteTCP cliente = new ClienteTCP();
CharSequence cs = cliente.sendMessage("Hola Mundo");
if ( cs != null)
debugText.setText(cs);
else
debugText.setText("ERROR OCURRED");
}
}
I'm sorry due to big code, but I'm going to cry ://///
If you try to connect to "localhost" from the Android device, it will try to connect to a service on the Android device because, on whatever device you are running, that is the "local host".
Since the service is running on your machine, it needs to be referenced via an IP address that is reachable by the Android device. That means that if the phone/tablet/whatever is connected to your local WiFi, any 192.168.*.* (private network) address should connect just fine but if it's on the public Internet (via a cellular network, for example) then it'll require the public IP address of your machine or of another device, such as a firewall, that will forward the port to your machine on your internal network.
Try change TCP_HOST from localhost to 10.0.2.2
I made a program which can connect bluetooth to my device and getting byte from my device.
But the program cannot running in the background.
I only want to get byte in the background.
I made another class which extend Service and trying to make my program run.
public class NickyService extends Service {
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent,flags,startId);
//Wrong code
MainActivity a1 = new MainActivity();
return START_NOT_STICKY;
}
}
I have no idea with fixing this.
How do I fix this big problem?
The following codes is right!
It can get byte and connect to device,but cannot running in the background!!
MainActivity.java
package com.example.bluetooth10;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import org.apache.http.util.ByteArrayBuffer;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Vibrator;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity {
// textview for connection status
ListView pairedListView;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
TextView sensorView0, title_paired_devices;
String paired = "";
Handler bluetoothIn;
private TextView connecting_str;
private TextView textView1;
final int handlerState = 0; // used to identify handler message
private BluetoothAdapter btAdapter = null;
private BluetoothSocket btSocket = null;
private ByteArrayBuffer baf1 = new ByteArrayBuffer(32);
String path = Environment.getExternalStorageDirectory().toString();
private ConnectedThread mConnectedThread;
private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // SPP UUID service - this should work for most devices
private static String address; // String for MAC address
protected void onHandleIntent(Intent workIntent) {
// Gets data from the incoming Intent
String dataString = workIntent.getDataString();
// Do work here, based on the contents of dataString
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.textView1);
title_paired_devices = (TextView) findViewById(R.id.title_paired_devices);
...
bluetoothIn = new Handler() {
public void handleMessage(android.os.Message msg) {
connecting_str.setText("Connection!!");
byte[] readBuf = (byte[]) msg.obj; // obj = buffer from connect thread
for (int i=0; i<msg.arg1; i++) {
baf1.append((byte)readBuf[i]);
if (baf1.length()>1){
String str1 = String.format("%02X",(byte)baf1.byteAt(baf1.length()-2));
String str2 = String.format("%02X",(byte)baf1.byteAt(baf1.length()-1));
if (str1.equals("01") && str2.equals("FF")){
int tmpb = (byte)baf1.byteAt(13);
baf1.clear();
}
}
}
}
int toInt( byte[] bytes ) {
int result = 0;
for (int i=0; i<bytes.length; i++) {
result = ( result << 8 ) - Byte.MIN_VALUE + (int) bytes[i];
}
return result;
}
};
btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
checkBTState();
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException
{
return device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//creates secure outgoing connecetion with BT device using UUID
}
public void onResume() {
super.onResume();
checkBTState();
btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);//make title viewable
for (BluetoothDevice device : pairedDevices) {
if (!paired.equals("")) paired = paired + ",";
paired = paired + device.getName() + ";" + device.getAddress();
}
} else {
paired = "no devices paired";
}
String str0[] = paired.split(",");
String str1 = str0[0]; //pairedListView.getItemAtPosition(0).toString(); //Get MAC address from DeviceListActivity
String str2[] = str1.split(";");
address = str2[1]; //Get the MAC address from the DeviceListActivty via EXTRA
BluetoothDevice device = btAdapter.getRemoteDevice(address); //create device and set the MAC address
try {
btSocket = createBluetoothSocket(device);
} catch (IOException e) {
Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
}
try {
btSocket.connect();
} catch (IOException e) {
try {
btSocket.close();
} catch (IOException e2) { }
}
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
}
public void onPause() {
super.onPause();
try {
btSocket.close(); //Don't leave Bluetooth sockets open when leaving activity
} catch (IOException e2) { }
}
private void checkBTState() {
btAdapter = BluetoothAdapter.getDefaultAdapter(); // CHECK THIS OUT THAT IT WORKS!!!
if(btAdapter==null) {
Toast.makeText(getBaseContext(), "Device does not support Bluetooth", Toast.LENGTH_SHORT).show();
finish();
} else {
if (!btAdapter.isEnabled()) {
//Prompt user to turn on Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, 1);
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
// ***********************************************************
// create new class for connect thread
// ***********************************************************
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
//creation of the connect thread
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
//Create I/O streams for connection
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[40]; //The arduino is sending a small amount of data so a large buffer is not needed
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer); //read bytes from input buffer
bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget(); //Send message to handler
} catch (IOException e) {
break;
}
}
}
}
}