Unverified Commit 6600f903 authored by Li Li's avatar Li Li Committed by Jeffrey I. Schiller

Added Property DisconnectOnError to BluetoothClient

Change-Id: I872e3740a1db8a7ddf97ee38b030f90fc2a00b53
parent 25a9095e
......@@ -552,6 +552,11 @@ public final class YoungAndroidFormUpgrader {
// No properties need to be modified to upgrade to version 5.
srcCompVersion = 5;
}
if (srcCompVersion < 6) {
// The BluetoothClient.DisconnectOnError property was added.
// No properties need to be modified to upgrade to version 6.
srcCompVersion = 6;
}
return srcCompVersion;
}
......
......@@ -1247,7 +1247,11 @@ Blockly.Versioning.AllUpgradeMaps =
// The BluetoothClient.Secure property was added.
// No blocks need to be modified to upgrade to version 5.
5: "noUpgrade"
5: "noUpgrade",
// The BluetoothClient.DisconnectOnError property was added.
// No blocks need to be modified to upgrade to version 5.
6: "noUpgrade"
}, // End BluetoothClient upgraders
......
......@@ -677,7 +677,9 @@ public class YaVersion {
// - The BluetoothClient.DelimiterByte property was added.
// For BLUETOOTHCLIENT_COMPONENT_VERSION 5:
// - The BluetoothClient.Secure property was added.
public static final int BLUETOOTHCLIENT_COMPONENT_VERSION = 5;
// For BLUETOOTHCLIENT_COMPONENT_VERSION 6:
// - The BluetoothClient.DisconnectOnError property was added.
public static final int BLUETOOTHCLIENT_COMPONENT_VERSION = 6;
// For BLUETOOTHSERVER_COMPONENT_VERSION 2:
// - The BluetoothServer.Enabled property was added.
......
......@@ -7,12 +7,14 @@
package com.google.appinventor.components.runtime;
import com.google.appinventor.components.annotations.DesignerComponent;
import com.google.appinventor.components.annotations.DesignerProperty;
import com.google.appinventor.components.annotations.PropertyCategory;
import com.google.appinventor.components.annotations.SimpleFunction;
import com.google.appinventor.components.annotations.SimpleObject;
import com.google.appinventor.components.annotations.SimpleProperty;
import com.google.appinventor.components.annotations.UsesPermissions;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.common.PropertyTypeConstants;
import com.google.appinventor.components.common.YaVersion;
import com.google.appinventor.components.runtime.util.BluetoothReflection;
import com.google.appinventor.components.runtime.util.ErrorMessages;
......@@ -55,6 +57,28 @@ public final class BluetoothClient extends BluetoothConnectionBase {
*/
public BluetoothClient(ComponentContainer container) {
super(container, "BluetoothClient");
DisconnectOnError(false);
}
/**
* Returns whether BluetoothClient/BluetoothServer should be disconnected automatically when an error occurs.
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR,
description = "Disconnects BluetoothClient automatically when an error occurs.")
public boolean DisconnectOnError() {
return disconnectOnError;
}
/**
* Specifies whether BluetoothClient/BluetoothServer should be disconnected automatically when an error occurs.
*
* @param disconnectOnError {@code true} to disconnect BluetoothClient/BluetoothServer automatically when an error occurs.
*/
@DesignerProperty(editorType = PropertyTypeConstants.PROPERTY_TYPE_BOOLEAN,
defaultValue = "False")
@SimpleProperty
public void DisconnectOnError(boolean disconnectOnError) {
this.disconnectOnError = disconnectOnError;
}
boolean attachComponent(Component component, Set<Integer> acceptableDeviceClasses) {
......
......@@ -48,23 +48,27 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
private ByteOrder byteOrder;
private String encoding;
private byte delimiter;
protected boolean disconnectOnError;
protected boolean secure;
private Object connectedBluetoothSocket;
private InputStream inputStream;
private OutputStream outputStream;
private final int sdkLevel;
/**
* Creates a new BluetoothConnectionBase.
*/
protected BluetoothConnectionBase(ComponentContainer container, String logTag) {
this(container.$form(), logTag);
this(container.$form(), logTag, SdkLevel.getLevel());
form.registerForOnDestroy(this);
}
private BluetoothConnectionBase(Form form, String logTag) {
private BluetoothConnectionBase(Form form, String logTag, int sdkLevel) {
super(form);
this.logTag = logTag;
this.sdkLevel = sdkLevel;
this.disconnectOnError = false;
HighByteFirst(false); // Lego Mindstorms NXT is low-endian, so false is a good default.
CharacterEncoding("UTF-8");
......@@ -76,7 +80,7 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
* This constructor is for testing purposes only.
*/
protected BluetoothConnectionBase(OutputStream outputStream, InputStream inputStream) {
this((Form) null, (String) null);
this((Form) null, (String) null, SdkLevel.LEVEL_ECLAIR_MR1);
this.connectedBluetoothSocket = "Not Null";
this.outputStream = outputStream;
this.inputStream = inputStream;
......@@ -192,11 +196,22 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
/**
* Returns `frue`{:.logic.block} if a connection to a Bluetooth device has been made.
*/
@SimpleProperty(category = PropertyCategory.BEHAVIOR)
@SimpleProperty(category = PropertyCategory.BEHAVIOR,
description = "On devices with API level 14 (LEVEL_ICE_CREAM_SANDWICH) or higher, " +
"this property returned is accurate. But on old devices with API level lower than 14, " +
"it may not return the current state of connection(e.g., it might be disconnected but you " +
"may not know until you attempt to read/write the socket.")
public final boolean IsConnected() {
return (connectedBluetoothSocket != null);
if (sdkLevel >= SdkLevel.LEVEL_ICE_CREAM_SANDWICH) {
return (connectedBluetoothSocket != null && BluetoothReflection.isBluetoothSocketConnected(connectedBluetoothSocket));
} else {
return (connectedBluetoothSocket != null);
}
}
protected boolean DisconnectOnError() {
return disconnectOnError;
}
/**
* Whether to invoke SSP (Simple Secure Pairing), which is supported on devices with Bluetooth
* v2.1 or higher. When working with embedded Bluetooth devices, this property may need to be set
......@@ -506,6 +521,10 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
outputStream.write(b);
outputStream.flush();
} catch (IOException e) {
Log.e(logTag, "IO Exception during Writing" + e.getMessage());
if (disconnectOnError) {
Disconnect();
}
bluetoothError(functionName,
ErrorMessages.ERROR_BLUETOOTH_UNABLE_TO_WRITE, e.getMessage());
}
......@@ -528,6 +547,10 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
outputStream.write(bytes);
outputStream.flush();
} catch (IOException e) {
Log.e(logTag, "IO Exception during Writing" + e.getMessage());
if (disconnectOnError) {
Disconnect();
}
bluetoothError(functionName,
ErrorMessages.ERROR_BLUETOOTH_UNABLE_TO_WRITE, e.getMessage());
}
......@@ -549,6 +572,10 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
try {
return inputStream.available();
} catch (IOException e) {
Log.e(logTag, "IO Exception during Getting Receive Availability " + e.getMessage());
if (disconnectOnError) {
Disconnect();
}
bluetoothError(functionName,
ErrorMessages.ERROR_BLUETOOTH_UNABLE_TO_READ, e.getMessage());
return 0;
......@@ -771,6 +798,10 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
}
totalBytesRead += numBytesRead;
} catch (IOException e) {
Log.e(logTag, "IO Exception during Reading " + e.getMessage());
if (disconnectOnError) {
Disconnect();
}
bluetoothError(functionName,
ErrorMessages.ERROR_BLUETOOTH_UNABLE_TO_READ, e.getMessage());
break;
......@@ -792,6 +823,10 @@ public abstract class BluetoothConnectionBase extends AndroidNonvisibleComponent
break;
}
} catch (IOException e) {
Log.e(logTag, "IO Exception during Reading " + e.getMessage());
if (disconnectOnError) {
Disconnect();
}
bluetoothError(functionName,
ErrorMessages.ERROR_BLUETOOTH_UNABLE_TO_READ, e.getMessage());
break;
......
......@@ -266,6 +266,17 @@ public class BluetoothReflection {
bluetoothSocket);
}
/**
* Invokes the method
* {@link android.bluetooth.BluetoothSocket#isConnected()}.
*
* @param bluetoothSocket a {@link android.bluetooth.BluetoothSocket} object
*/
public static boolean isBluetoothSocketConnected(Object bluetoothSocket) {
return (Boolean)invokeMethod(getMethod(bluetoothSocket.getClass(), "isConnected"),
bluetoothSocket);
}
/**
* Invokes the method
* {@link android.bluetooth.BluetoothSocket#getInputStream()}.
......
......@@ -256,6 +256,8 @@ set the following properties:
<dd>Returns the delimiter byte to use when passing a negative number for the
numberOfBytes parameter when calling ReceiveText, ReceiveSignedBytes, or
ReceiveUnsignedBytes.</dd>
<dt id="BluetoothClient.DisconnectOnError" class="boolean"><em>DisconnectOnError</em></dt>
<dd>Specifies whether BluetoothClient/BluetoothServer should be disconnected automatically when an error occurs.</dd>
<dt id="BluetoothClient.Enabled" class="boolean ro bo"><em>Enabled</em></dt>
<dd>Returns <code class="logic block highlighter-rouge">true</code> if Bluetooth is enabled, <code class="logic block highlighter-rouge">false</code> otherwise.</dd>
<dt id="BluetoothClient.HighByteFirst" class="boolean"><em>HighByteFirst</em></dt>
......
......@@ -140,6 +140,9 @@ Use `BluetoothClient` to connect your device to other devices using Bluetooth. T
numberOfBytes parameter when calling ReceiveText, ReceiveSignedBytes, or
ReceiveUnsignedBytes.
{:id="BluetoothClient.DisconnectOnError" .boolean} *DisconnectOnError*
: Specifies whether BluetoothClient/BluetoothServer should be disconnected automatically when an error occurs.
{:id="BluetoothClient.Enabled" .boolean .ro .bo} *Enabled*
: Returns `true`{:.logic.block} if Bluetooth is enabled, `false`{:.logic.block} otherwise.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment