This commit is contained in:
Harald Hoyer 2017-04-26 15:26:07 +02:00 committed by Harald Hoyer
parent e2fded1068
commit 0459ddc966
7 changed files with 261 additions and 193 deletions

View file

@ -80,27 +80,14 @@
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" /> <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" /> <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" /> <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content> </content>

View file

@ -45,6 +45,8 @@ import android.widget.Toast;
import com.example.android.bluetoothchat.R; import com.example.android.bluetoothchat.R;
import org.surfsite.iconsole.common.logger.Log; import org.surfsite.iconsole.common.logger.Log;
import java.util.Locale;
/** /**
* This fragment controls Bluetooth to communicate with other devices. * This fragment controls Bluetooth to communicate with other devices.
*/ */
@ -59,8 +61,9 @@ public class BluetoothChatFragment extends Fragment {
// Layout Views // Layout Views
private ListView mConversationView; private ListView mConversationView;
private EditText mOutEditText; private Button mStartButton;
private Button mSendButton; private Button mStopButton;
private Button mDisconnectButton;
/** /**
* Name of the connected device * Name of the connected device
@ -72,11 +75,6 @@ public class BluetoothChatFragment extends Fragment {
*/ */
private ArrayAdapter<String> mConversationArrayAdapter; private ArrayAdapter<String> mConversationArrayAdapter;
/**
* String buffer for outgoing messages
*/
private StringBuffer mOutStringBuffer;
/** /**
* Local Bluetooth adapter * Local Bluetooth adapter
*/ */
@ -150,8 +148,9 @@ public class BluetoothChatFragment extends Fragment {
@Override @Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mConversationView = (ListView) view.findViewById(R.id.in); mConversationView = (ListView) view.findViewById(R.id.in);
mOutEditText = (EditText) view.findViewById(R.id.edit_text_out); mStartButton = (Button) view.findViewById(R.id.button_start);
mSendButton = (Button) view.findViewById(R.id.button_send); mStopButton = (Button) view.findViewById(R.id.button_stop);
mDisconnectButton = (Button) view.findViewById(R.id.button_disconnect);
} }
/** /**
@ -165,27 +164,30 @@ public class BluetoothChatFragment extends Fragment {
mConversationView.setAdapter(mConversationArrayAdapter); mConversationView.setAdapter(mConversationArrayAdapter);
// Initialize the compose field with a listener for the return key
mOutEditText.setOnEditorActionListener(mWriteListener);
// Initialize the send button with a listener that for click events
mSendButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Send a message using content of the edit text widget
View view = getView();
if (null != view) {
TextView textView = (TextView) view.findViewById(R.id.edit_text_out);
String message = textView.getText().toString();
sendMessage(message);
}
}
});
// Initialize the BluetoothChatService to perform bluetooth connections // Initialize the BluetoothChatService to perform bluetooth connections
mChatService = new BluetoothChatService(getActivity(), mHandler); mChatService = new BluetoothChatService(getActivity(), mHandler);
// Initialize the buffer for outgoing messages mStartButton.setOnClickListener(new View.OnClickListener() {
mOutStringBuffer = new StringBuffer(""); public void onClick(View v) {
mChatService.startIConsole();
}
});
mStopButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mChatService.stopIConsole();
}
});
mDisconnectButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mChatService.stop();
}
});
mStartButton.setEnabled(false);
mStopButton.setEnabled(false);
mDisconnectButton.setEnabled(false);
} }
/** /**
@ -212,32 +214,8 @@ public class BluetoothChatFragment extends Fragment {
return; return;
} }
// Check that there's actually something to send mChatService.startIConsole();
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);
}
return true;
}
};
/** /**
* Updates the status on the action bar. * Updates the status on the action bar.
@ -286,16 +264,32 @@ public class BluetoothChatFragment extends Fragment {
case BluetoothChatService.STATE_CONNECTED: case BluetoothChatService.STATE_CONNECTED:
setStatus(getString(R.string.title_connected_to, mConnectedDeviceName)); setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
mConversationArrayAdapter.clear(); mConversationArrayAdapter.clear();
mStartButton.setEnabled(true);
mStopButton.setEnabled(true);
mDisconnectButton.setEnabled(true);
break; break;
case BluetoothChatService.STATE_CONNECTING: case BluetoothChatService.STATE_CONNECTING:
setStatus(R.string.title_connecting); setStatus(R.string.title_connecting);
mStartButton.setEnabled(false);
mStopButton.setEnabled(false);
mDisconnectButton.setEnabled(false);
break; break;
case BluetoothChatService.STATE_LISTEN: case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE: case BluetoothChatService.STATE_NONE:
setStatus(R.string.title_not_connected); setStatus(R.string.title_not_connected);
mStartButton.setEnabled(false);
mStopButton.setEnabled(false);
mDisconnectButton.setEnabled(false);
break; break;
} }
break; break;
case Constants.MESSAGE_DATA:
IConsole.Data data = (IConsole.Data) msg.obj;
String dataMessage = String.format(Locale.US, "Time: %s Speed: %f Power: %f RPM: %d LVL: %d Dist: %f Cal: %d HF: %d",
data.mTime, data.mSpeed10 / 10.0, data.mPower10 / 10.0, data.mRPM,
data.mLevel, data.mDistance10 / 10.0, data.mCalories, data.mHF);
mConversationArrayAdapter.add(mConnectedDeviceName + ": " + dataMessage);
break;
case Constants.MESSAGE_WRITE: case Constants.MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj; byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer // construct a string from the buffer

View file

@ -203,13 +203,12 @@ public class BluetoothChatService {
updateUserInterfaceTitle(); updateUserInterfaceTitle();
} }
/** public synchronized boolean startIConsole() {
* Write to the ConnectedThread in an unsynchronized manner return mConnectedThread.startIConsole();
* }
* @param out The bytes to write
* @see ConnectedThread#write(byte[]) public synchronized boolean stopIConsole() {
*/ return mConnectedThread.startIConsole();
public void write(byte[] out) {
} }
/** /**
@ -346,8 +345,10 @@ public class BluetoothChatService {
mmIConsole = new IConsole(mmInStream, mmOutStream, new IConsole.DataListener() { mmIConsole = new IConsole(mmInStream, mmOutStream, new IConsole.DataListener() {
@Override @Override
public void onData(IConsole.Data data) { public void onData(IConsole.Data data) {
Log.i(TAG, "mConnectedThread: " + data.toString()); Log.i(TAG, "mConnectedThread: onData");
/* print */ // Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_DATA, -1, -1, data)
.sendToTarget();
} }
@Override @Override
@ -361,7 +362,7 @@ public class BluetoothChatService {
@Override @Override
public void onRead(byte[] buffer) { public void onRead(byte[] buffer) {
if (buffer.length > 0) { if (buffer.length > 0) {
String hexbuf = IConsole.byteArrayToHex(Arrays.copyOfRange(buffer, 0, buffer.length)) + '\n'; String hexbuf = IConsole.byteArrayToHex(Arrays.copyOfRange(buffer, 0, buffer.length));
// Send the obtained bytes to the UI Activity // Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_READ, hexbuf.length(), -1, hexbuf.getBytes()) mHandler.obtainMessage(Constants.MESSAGE_READ, hexbuf.length(), -1, hexbuf.getBytes())
@ -371,7 +372,7 @@ public class BluetoothChatService {
@Override @Override
public void onWrite(byte[] buffer) { public void onWrite(byte[] buffer) {
String hexbuf = IConsole.byteArrayToHex(buffer) + '\n'; String hexbuf = IConsole.byteArrayToHex(buffer);
// Share the sent message back to the UI Activity // Share the sent message back to the UI Activity
mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, hexbuf.getBytes()) mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, hexbuf.getBytes())
@ -383,15 +384,25 @@ public class BluetoothChatService {
public void run() { public void run() {
Log.i(TAG, "BEGIN mConnectedThread"); Log.i(TAG, "BEGIN mConnectedThread");
mmIConsole.start();
while (mState == STATE_CONNECTED) { while (mState == STATE_CONNECTED) {
if (!mmIConsole.processIO()) if (!mmIConsole.processIO())
break; break;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
; // ignore
} }
} }
}
public boolean setLevel(int level) { public boolean setLevel(int level) {
return mmIConsole.setLevel(level); return mmIConsole.setLevel(level);
} }
public boolean startIConsole() { return mmIConsole.start(); }
public boolean stopIConsole() { return mmIConsole.stop(); }
public void cancel() { public void cancel() {
mmIConsole.stop(); mmIConsole.stop();

View file

@ -27,6 +27,7 @@ public interface Constants {
public static final int MESSAGE_WRITE = 3; public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4; public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5; public static final int MESSAGE_TOAST = 5;
public static final int MESSAGE_DATA = 6;
// Key names received from the BluetoothChatService Handler // Key names received from the BluetoothChatService Handler
public static final String DEVICE_NAME = "device_name"; public static final String DEVICE_NAME = "device_name";

View file

@ -1,7 +1,10 @@
package org.surfsite.iconsole; package org.surfsite.iconsole;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Arrays;
import java.util.concurrent.TimeoutException;
/** /**
* Created by harald on 25.04.17. * Created by harald on 25.04.17.
@ -10,7 +13,7 @@ import java.io.OutputStream;
class IConsole { class IConsole {
private static final byte[] PING = {(byte) 0xf0, (byte) 0xa0, (byte) 0x01, (byte) 0x01, (byte) 0x92 }; private static final byte[] PING = {(byte) 0xf0, (byte) 0xa0, (byte) 0x01, (byte) 0x01, (byte) 0x92 };
private static final byte[] INIT_A0 = {(byte) 0xf0, (byte) 0xa0, 0x02, 0x02, (byte) 0x94}; private static final byte[] INIT_A0 = {(byte) 0xf0, (byte) 0xa0, 0x02, 0x02, (byte) 0x94};
private static final byte[] PONG = {(byte) 0xf0, (byte) 0xb0, 0x01, 0x01, (byte) 0xa2}; //private static final byte[] PONG = {(byte) 0xf0, (byte) 0xb0, 0x01, 0x01, (byte) 0xa2};
private static final byte[] STATUS = {(byte) 0xf0, (byte) 0xa1, 0x01, 0x01, (byte) 0x93}; private static final byte[] STATUS = {(byte) 0xf0, (byte) 0xa1, 0x01, 0x01, (byte) 0x93};
private static final byte[] INIT_A3 = {(byte) 0xf0, (byte) 0xa3, 0x01, 0x01, 0x01, (byte) 0x96}; private static final byte[] INIT_A3 = {(byte) 0xf0, (byte) 0xa3, 0x01, 0x01, 0x01, (byte) 0x96};
private static final byte[] INIT_A4 = {(byte) 0xf0, (byte) 0xa4, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, (byte) 0xa0}; private static final byte[] INIT_A4 = {(byte) 0xf0, (byte) 0xa4, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, (byte) 0xa0};
@ -24,6 +27,7 @@ class IConsole {
PING, PING,
A0, A0,
A1, A1,
A1_POST_PING,
A3, A3,
A4, A4,
START, START,
@ -32,9 +36,13 @@ class IConsole {
SETLEVEL, SETLEVEL,
} }
private State mCurrentState; private State mCurrentState = State.BEGIN;
private State mNextState; private State mNextState = State.PING;
private int mSetLevel; private boolean mWaitAck = false;
private int mSetLevel = 1;
private long mTimesent = 0;
private int mExpectLen = 0;
private byte[] mExpectPacket;
private final InputStream mInputStream; private final InputStream mInputStream;
private final OutputStream mOutputStream; private final OutputStream mOutputStream;
private final DataListener mDataListener; private final DataListener mDataListener;
@ -45,12 +53,9 @@ class IConsole {
this.mOutputStream = outputStream; this.mOutputStream = outputStream;
this.mDataListener = dataListener; this.mDataListener = dataListener;
this.mDebugListener = debugListener; this.mDebugListener = debugListener;
this.mCurrentState = State.BEGIN;
this.mNextState = State.PING;
this.mSetLevel = 1;
} }
class Data { class Data implements java.io.Serializable {
long mTime; // in seconds long mTime; // in seconds
int mSpeed10; int mSpeed10;
int mRPM; int mRPM;
@ -93,21 +98,17 @@ class IConsole {
void onWrite(byte[] bytes); void onWrite(byte[] bytes);
} }
boolean processIO() { boolean start() {
synchronized (this) { synchronized (this) {
Data data = new Data(0, 0, 0, 0, 0, 0, 0, 0); this.mNextState = State.A0;
if (null != mDebugListener) {
mDebugListener.onWrite(PING);
mDebugListener.onRead(PONG);
}
mDataListener.onData(data);
} }
return true; return true;
} }
boolean stop() { boolean stop() {
synchronized (this) {
this.mNextState = State.STOP;
}
return true; return true;
} }
@ -116,121 +117,190 @@ class IConsole {
if (mCurrentState != State.READ) if (mCurrentState != State.READ)
return false; return false;
this.mCurrentState = State.SETLEVEL; this.mNextState = State.SETLEVEL;
this.mNextState = State.READ;
this.mSetLevel = level; this.mSetLevel = level;
} }
return true; return true;
} }
/* boolean send(byte[] packet, byte expect, int plen) throws IOException {
def send_ack(packet, expect=None, plen=0): long now = System.currentTimeMillis();
if expect == None:
expect = 0xb0 | (ord(packet[1]) & 0xF)
if plen == 0: if ((now - mTimesent) < 200) {
plen = len(packet) return false;
}
got = None // Flush input stream
while got == None: try {
sleep(0.1) mInputStream.skip(mInputStream.available());
sock.sendall(packet) } catch (IOException e) {
i = 0 ; // ignore
while got == None and i < 6: }
i+=1
sleep(0.1)
got = sock.recv(plen)
if len(got) == plen:
#print "<-" + hexlify(got)
pass
else:
if len(got) > 0:
#print "Got len == %d" % len(got)
pass
got = None
if got and len(got) >= 3 and got[0] == packet[0] and ord(got[1]) == expect: // Send packet
break mOutputStream.write(packet);
got = None
#print "---> Retransmit"
return got
def send_level(lvl): if (null != mDataListener)
packet = struct.pack('BBBBBB', 0xf0, 0xa6, 0x01, 0x01, lvl+1, (0xf0+0xa6+3+lvl) & 0xFF) mDebugListener.onWrite(packet);
got = send_ack(packet)
return got
*/ mTimesent = System.currentTimeMillis();
mExpectPacket = packet;
mExpectPacket[1] = expect;
mExpectLen = plen;
mWaitAck = true;
return true;
}
/* private boolean send(byte[] packet) throws IOException {
send_ack(PING) return send(packet, (byte)(0xb0 | (packet[1] & 0xF)), packet.length);
prints(win, "ping done") }
send_ack(INIT_A0, expect=0xb7, plen=6) private boolean send(byte[] packet, int plen) throws IOException {
prints(win, "A0 done") return send(packet, (byte)(0xb0 | (packet[1] & 0xF)), plen);
}
for i in range(0, 5): private boolean send_level(int level) throws IOException {
send_ack(PING) byte[] packet = SETLEVEL.clone();
prints(win, "ping done") packet[4] = (byte) (packet[4] + level);
packet[5] = (byte) ((packet[5] + level) & 0xFF);
return send(packet);
}
send_ack(STATUS, plen=6) private byte[] wait_ack() throws IOException, TimeoutException {
prints(win, "status done") byte[] buffer = new byte[mExpectLen];
int bytes;
send_ack(PING) long now = System.currentTimeMillis();
prints(win, "ping done")
send_ack(INIT_A3) if ((now - mTimesent) > 1000000) {
prints(win, "A3 done") mWaitAck = false;
return null;
}
send_ack(INIT_A4) if (mInputStream.available() < mExpectLen)
prints(win, "A4 done") return null;
send_ack(START) bytes = mInputStream.read(buffer);
prints(win, "START done")
level = 1 if (null != mDebugListener)
mDebugListener.onRead(Arrays.copyOfRange(buffer, 0, bytes));
while True: if (bytes != mExpectLen) {
sleep(0.25) throw new IOException("Wrong number of bytes read. Expected " + mExpectLen + ", got " + bytes);
while True: }
key = win.getch()
if key == ord('q'):
return
elif key == ord('a') or key == curses.KEY_UP or key == curses.KEY_RIGHT:
if level < 31:
level += 1
prints(win, "Level: %d" % level)
send_level(level)
elif key == ord('y') or key == curses.KEY_DOWN or key == curses.KEY_LEFT: if (buffer[0] != mExpectPacket[0]) {
if level > 1: throw new IOException("Byte 0 wrong. Expected " + String.format("%02x", mExpectPacket[0]) + ", got " + String.format("%02x", buffer[0]));
level -= 1 }
prints(win, "Level: %d" % level)
send_level(level)
elif key == -1:
break
got = send_ack(READ, plen=21) if (buffer[1] != mExpectPacket[1]) {
if len(got) == 21: throw new IOException("Byte 1 wrong. Expected " + String.format("%02x", mExpectPacket[1]) + ", got " + String.format("%02x", buffer[1]));
ic = IConsole(got) }
power_meter.update(power = ic.power, cadence = ic.rpm)
speed.update(ic.speed)
win.addstr(0,0, "%s - %s - %s - %s - %s - %s - %s - %s" % (ic.time_str,
ic.speed_str,
ic.rpm_str,
ic.distance_str,
ic.calories_str,
ic.hf_str,
ic.power_str,
ic.lvl_str))
*/ return buffer;
}
/* private boolean processIOSend() throws IOException {
send_ack(STOP) switch (mCurrentState) {
send_ack(PING) case BEGIN:
mCurrentState = mNextState;
break;
case PING:
send(PING);
break;
case A0:
send(INIT_A0, (byte)0xb7, 6);
break;
case A1:
send(STATUS, 6);
break;
case A1_POST_PING:
send(PING);
break;
case A3:
send(INIT_A3);
break;
case A4:
send(INIT_A4);
break;
case START:
send(START);
break;
case STOP:
send(STOP);
break;
case READ:
send(READ);
break;
case SETLEVEL:
send_level(mSetLevel);
break;
}
return true;
}
*/ private boolean processIOAck() throws IOException, TimeoutException {
byte[] got = null;
got = wait_ack();
if (null == got)
return true;
if(mCurrentState == State.READ)
mDataListener.onData(new Data(got));
mCurrentState = mNextState;
switch (mNextState) {
case BEGIN:
mNextState = State.PING;
break;
case PING:
mNextState = State.PING;
break;
case A0:
mNextState = State.A1;
break;
case A1:
mNextState = State.A1_POST_PING;
break;
case A1_POST_PING:
mNextState = State.A3;
break;
case A3:
mNextState = State.A4;
break;
case A4:
mNextState = State.START;
break;
case START:
mNextState = State.READ;
break;
case STOP:
mNextState = State.PING;
break;
case READ:
mNextState = State.READ;
break;
case SETLEVEL:
mNextState = State.READ;
break;
}
return true;
}
boolean processIO() {
synchronized (this) {
try {
if (! mWaitAck) {
return processIOSend();
} else {
return processIOAck();
}
} catch (Exception e) {
mDataListener.onError(e);
return false;
}
}
}
static byte[] hexStringToByteArray(String s) { static byte[] hexStringToByteArray(String s) {
int len = s.length(); int len = s.length();

View file

@ -32,18 +32,21 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" > android:orientation="horizontal" >
<EditText
android:id="@+id/edit_text_out"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_weight="1" />
<Button <Button
android:id="@+id/button_send" android:id="@+id/button_start"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/send" /> android:text="@string/start" />
<Button
android:id="@+id/button_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop" />
<Button
android:id="@+id/button_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disconnect" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View file

@ -17,7 +17,6 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- BluetoothChat --> <!-- BluetoothChat -->
<string name="send">Send</string>
<string name="not_connected">You are not connected to a device</string> <string name="not_connected">You are not connected to a device</string>
<string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string> <string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string>
<string name="title_connecting">connecting...</string> <string name="title_connecting">connecting...</string>
@ -37,5 +36,8 @@
<string name="secure_connect">Connect a device - Secure</string> <string name="secure_connect">Connect a device - Secure</string>
<string name="insecure_connect">Connect a device - Insecure</string> <string name="insecure_connect">Connect a device - Insecure</string>
<string name="discoverable">Make discoverable</string> <string name="discoverable">Make discoverable</string>
<string name="start">Start</string>
<string name="stop">Stop</string>
<string name="disconnect">Disconnect</string>
</resources> </resources>