I am trying to read serial data from a USB device using my Samsung phone as the host. I have followed the USB Host Overview tutorial closely but I cannot get any data from the device. I am performing async read using UsbRequest as the device is continually streaming data I would like to read.
My Java code:
class TransferThread extends Thread {
private static final String TAG = "MainActivity";
private static int TIMEOUT = 5000;
private static int BUFFER_LENGTH = 32768;
private byte[] buffer = new byte[BUFFER_LENGTH];
UsbDeviceConnection connection;
UsbEndpoint endpoint;
TransferThread(UsbDeviceConnection connection, UsbEndpoint endpoint) {
this.connection = connection;
this.endpoint = endpoint;
}
public void run() {
Log.v(TAG, "New thread started");
UsbRequest usbRequest = new UsbRequest();
if(usbRequest.initialize(connection, endpoint)) {
Log.v(TAG, "USB request successfully initialised");
}
final ByteBuffer byteBuffer = ByteBuffer.allocate(BUFFER_LENGTH);
if(usbRequest.queue(byteBuffer)) {
Log.v(TAG, "USB request successfully queued");
}
if(connection.requestWait() == usbRequest) {
Log.v(TAG, "Successfully returned USB request result");
Log.v(TAG, "Has array: " + byteBuffer.hasArray());
Log.v(TAG, "Data: " + Arrays.toString(byteBuffer.array()));
Log.v(TAG, "Data: " + byteBuffer.toString());
}
else {
Log.v(TAG, "Failed to return USB request");
}
Log.v(TAG, "byteBuffer.ToString(): " + byteBuffer.toString());
/* int numBytesTransferred = connection.bulkTransfer(endpoint, buffer, buffer.length, TIMEOUT);
if(numBytesTransferred >= 0) {
Log.v(TAG, "Bulk transfer successful");
}
else {
Log.v(TAG, "Bulk transfer failed");
}*/
}
}
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION";
private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if(device != null){
Log.v(TAG,"Permission granted for device");
}
}
else {
Log.d(TAG, "permission denied for device " + device);
}
}
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "Running Main activity onCreate");
// Enumerate USB devices
UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Log.v(TAG, String.format("%d device(s) found by UsbManager", deviceList.size()));
for (HashMap.Entry<String, UsbDevice> entry : deviceList.entrySet()) {
String key = entry.getKey();
Log.v(TAG, "Device name: " + key);
}
UsbDevice device = deviceList.get("/dev/bus/usb/002/002");
Log.v(TAG, "Device info: " + device.toString());
Log.v(TAG, String.format("Device has %d configuration(s)", device.getConfigurationCount()));
Log.v(TAG, String.format("Device has %d interface(s)", device.getInterfaceCount()));
// Obtain permission to communicate with a device
PendingIntent permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), PendingIntent.FLAG_MUTABLE);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(usbReceiver, filter);
manager.requestPermission(device, permissionIntent);
int interfaceNumber = 0;
int endpointNumber = 0;
UsbInterface usbInterface = device.getInterface(interfaceNumber);
Log.v(TAG, String.format("Got interface %d", interfaceNumber));
Log.v(TAG, "Interface name: " + usbInterface.getName());
Log.v(TAG, "Interface class: Vendor specific " + usbInterface.getInterfaceClass());
UsbEndpoint endpoint = usbInterface.getEndpoint(endpointNumber);
Log.v(TAG, String.format("Got endpoint %d", endpointNumber));
int endpointType = endpoint.getType();
if(endpointType == UsbConstants.USB_ENDPOINT_XFER_CONTROL) {
Log.v(TAG, "Endpoint type: endpoint zero");
}
if(endpointType == UsbConstants.USB_ENDPOINT_XFER_ISOC) {
Log.v(TAG, "Endpoint type: isochronous endpoint");
}
if(endpointType == UsbConstants.USB_ENDPOINT_XFER_BULK) {
Log.v(TAG, "Endpoint type: bulk endpoint");
}
if(endpointType == UsbConstants.USB_ENDPOINT_XFER_INT) {
Log.v(TAG, "Endpoint type: interrupt endpoint");
}
int endpointDir = endpoint.getDirection();
if(endpointDir == UsbConstants.USB_DIR_IN) {
Log.v(TAG, "Endpoint direction: IN (device to host)");
}
if(endpointDir == UsbConstants.USB_DIR_OUT) {
Log.v(TAG, "Endpoint direction: OUT (host to device)");
}
UsbDeviceConnection connection = manager.openDevice(device);
connection.claimInterface(usbInterface, true);
TransferThread thread = new TransferThread(connection, endpoint);
thread.start();
}
}
Using endpoint 0 (interrupt type) I get the following data when I run the code:
Results in Logcat
I'm not sure if I'm using requestWait incorrectly or if I'm using the wrong endpoint or some other USB setting. Any help would be appreciated, thanks!
Related
I am having a bit of trouble trying to utilize the default Android dialog for popping up networks listed in the area. I have done some research and tried different avenues, but I haven't found anything that works correctly.
WifiManager mWifiManager;
List<ScanResult> mScanResults;
WifiListAdapter wifiListAdapter;
TextView hiddenVersionNumber;
String connectedSSID = "";
ProgressBar wifiNetworksLoading;
ArrayList<WifiItem> networkList = new ArrayList<>();
private static final int WEAK_WIFI_SIGNAL_STRENGTH = 1;
private final BroadcastReceiver mWifiScanReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context c, Intent intent) {
if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
List<ScanResult>mScanResults = mWifiManager.getScanResults();
//*unregisterReceiver(mWifiScanReceiver);*//
Log.d(TAG, "bozo " + mScanResults.size());
//*networkList.clear();
if (wifiNetworksLoading != null) {
wifiNetworksLoading.setVisibility(View.GONE);
}*//
ArrayList<WifiItem> list = new ArrayList<>();
for (ScanResult scan : mScanResults) {
//*Log.d(TAG, "bozo3 " + scan.SSID);*//
int level = WifiManager.calculateSignalLevel(scan.level, 4);
boolean isConnected = false;
Log.d(TAG, "bozo2 " + connectedSSID);
if (!connectedSSID.isEmpty()) {
Log.d(TAG, "bozo2 " + connectedSSID + " = " + scan.SSID);
if (connectedSSID.equalsIgnoreCase(scan.SSID)) {
isConnected = true;
}
}
if (!scan.SSID.isEmpty()) {
networkList.add(new WifiItem(scan.SSID, scan.capabilities, level, isConnected));
}
}
The OnCreate code listed below...
mWifiManager = (WifiManager)getApplicationContext().getSystemService(Context.WIFI_SERVICE);
//*registerReceiver(mWifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));*//
mWifiManager.startScan();
if (mWifiManager != null) {
mWifiManager.setWifiEnabled(true); // turn on Wifi
}
So for some reason my background service crashes, and I don't know why.
So my service contains BLE, and I bind to the service from the MainActivity with:
public void startBluetoothService() {
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
}
This runs, but then I get the following error
10-09 12:51:31.104 14007-14081/com.example.wrd I/ProviderInstaller: Installed default security provider GmsCore_OpenSSL
10-09 12:51:31.114 14007-14007/com.example.wrd D/AndroidRuntime: Shutting down VM
10-09 12:51:31.114 14007-14007/com.example.wrd E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.wrd, PID: 14007
java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3841)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.wrd.ble.BLE_Service> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:3838)
at android.app.ActivityThread.access$2100(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1909)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
My service looks like this:
public class BLE_Service extends Service {
private Home ma;
private boolean mscanning;
public boolean Read = false;
private Handler mHandler;
private long scanPeriod;
private int signalStrength;
//Intent string
private static String DeviceAddress;
private static final String TAG = "BLE_Service";
// Bluetooth objects that we need to interact with
private static BluetoothManager mBluetoothManager;
private static BluetoothAdapter mBluetoothAdapter;
private static BluetoothGatt mBluetoothGatt;
private static BluetoothDevice device;
private static BluetoothGattCharacteristic BLECharacterisitc;
private final static String BaseUuid = "00000000-0000-1000-8000-00805f9b34f";
private final static String CSUuid = "00002902-0000-1000-8000-00805f9b34fb";
private final static String UuidWrite = BaseUuid + "0";
private final static String UuidRead = BaseUuid + "1";
private final static String UuidRead2 = BaseUuid + "2";
private final static String state_RW = BaseUuid + "0";
private final static String treatmentSettings_RW = BaseUuid + "1";
private final static String adjustment_RW = BaseUuid + "2";
private final static String validation_R = BaseUuid + "3";
//Broadcasts
public final static String BROADCAST_ADDED = "added";
public final static String BROADCAST_ADDEDFrag = "added";
// Bluetooth characteristics that we need to read/write
private static BluetoothGattCharacteristic mCharacterisitc, mCharacterisitc2, mCharacterisitcWrite, mCharacterisitc_state_RW,
mCharacterisitc_treatmentSettings_RW, mCharacterisitc_adjustment_RW, mCharacterisitc_validation_R;
private static StringBuilder sb = new StringBuilder();
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connecting(String DeviceAddress) {
Log.d(TAG, "Connection State: connect");
device = mBluetoothAdapter.getRemoteDevice(DeviceAddress);
if (device == null) {
Log.d(TAG, "Connection State Device Not Available ");
return false;
} else {
Log.d(TAG, "Connection State Connecting...");
device.connectGatt(this, false, mGattCallback);
return true;
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean disconnect() {
mBluetoothGatt.disconnect();
mBluetoothGatt.close();
return true;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void checkConnectedDevices() {
if (mBluetoothGatt != null){
String DeviceString = mBluetoothGatt.getDevice().getAddress();
String NameString = mBluetoothGatt.getDevice().getName();
Log.d(TAG, "checkConnectedDevices: " + NameString);
//broadCastHEX(BROADCAST_ADDEDFrag, NameString+";"+DeviceString, "get_conn_BLE_return");
}else{
//broadCastHEX(BROADCAST_ADDEDFrag, null, "Connected_BLE_Devices_return");
}
}
public class LocalBinder extends Binder {
public BLE_Service getService() {
return BLE_Service.this;
}
}
private final IBinder mBinder = new LocalBinder();
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
/**
* Initializes a reference to the local Bluetooth adapter.
*
* #return Return true if the initialization is successful.
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean initialize() {
Log.d(TAG, "mBluetoothManager: service");
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (mBluetoothManager == null) {
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
Log.d(TAG, "mBluetoothManager: initialize");
BluetoothManager bluetoothManager = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
List<BluetoothDevice> devices = bluetoothManager.getConnectedDevices(BluetoothProfile.GATT);
Log.d(TAG, "mBluetoothManager: initialize device" + devices.toString());
for(BluetoothDevice device : devices) {
if(device.getType() == BluetoothDevice.DEVICE_TYPE_LE) {
Log.d(TAG, "mBluetoothManager: running loop" + device.getName() + "\n");
}else{
Log.d(TAG, "mBluetoothManager: nothing" + device.getName() + "\n");
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public BLE_Service(Home home, long scanPeriod, int signalStrength) {
ma = home;
mHandler = new Handler();
this.scanPeriod = scanPeriod;
this.signalStrength = signalStrength;
final BluetoothManager bluetoothManager =
(BluetoothManager) ma.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
public boolean isScanning() {
return mscanning;
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void start() {
if (!Utils.checkBluetooth(mBluetoothAdapter)) {
Utils.requestUserBluetooth(ma);
ma.stopScan();
} else {
scanLeDevice(true);
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void stop() {
scanLeDevice(false);
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void scanLeDevice(final boolean enable) {
if (enable && !mscanning) {
Utils.toast(ma.getApplication(), "Starting BLE Scan...");
mHandler.postDelayed(new Runnable() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void run() {
Utils.toast(ma.getApplicationContext(), "Stopping BLE scan...");
mscanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
ma.stopScan();
}
}, scanPeriod);
mscanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
}
}
private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
Log.d(TAG, "Connection State Change: " + status + " -> " + connectionState(newState));
gatt.discoverServices();
if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) {
/*
* Once successfully connected, we must next discover all the services on the
* device before we can read and write their characteristics.
*/
mBluetoothGatt = gatt;
BluetoothDevice device = gatt.getDevice();
Log.d(TAG, "Connection State onConnectionStateChange: " + device);
} else if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_DISCONNECTED) {
/*
* If at any point we disconnect, send a message to clear the weather values
* out of the UI
*/
Log.d(TAG, "Connection State: 2");
} else if (status != BluetoothGatt.GATT_SUCCESS) {
/*
* If there is a failure at any stage, simply disconnect
*/
}
}
/**
* This is called when a service discovery has completed.
*
* It gets the characteristics we are interested in and then
* broadcasts an update to the main activity.
*
* #param gatt The GATT database object
* #param status Status of whether the write was successful.
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, int status) {//prøv med ekstra status på denne
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService mBluetoothGattService = gatt.getService(UUID.fromString(CSUuid));
if (mBluetoothGattService != null) {
Log.i(TAG, "Connection State: Service characteristic UUID found: " + mBluetoothGattService.getUuid().toString());
mCharacterisitc = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead));
mCharacterisitc2 = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidRead2));
mCharacterisitcWrite = mBluetoothGattService.getCharacteristic(UUID.fromString(UuidWrite));
//First activate buttons here....
Log.w(TAG, "Connection State 1: mCharacterisitc " + mCharacterisitc + " " + mCharacterisitc2);
Intent broadcastIntent = new Intent().putExtra("ConnState", true);
broadcastIntent.setAction(BLE_Service.BROADCAST_ADDED);
LocalBroadcastManager.getInstance(BLE_Service.this).sendBroadcast(broadcastIntent);
if(Read){
readCharacteristic(gatt, mCharacterisitc);
}
} else {
Log.i(TAG, "Connection State: Service characteristic not found for UUID: " + UuidRead);
}
}
}
private String connectionState(int status) {
switch (status) {
case BluetoothProfile.STATE_CONNECTED:
return "Connection State: Connected";
case BluetoothProfile.STATE_DISCONNECTED:
return "Connection State: Disconnected";
case BluetoothProfile.STATE_CONNECTING:
return "Connection State: Connecting";
case BluetoothProfile.STATE_DISCONNECTING:
return "Connection State: Disconnecting";
default:
return String.valueOf(status);
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Connection State: onCharacteristicRead");
Log.w(TAG, "Connection State: Read 1");
// Verify that the read was the LED state
String uuid = characteristic.getUuid().toString();
// In this case, the only read the app does is the LED state.
// If the application had additional characteristics to read we could
// use a switch statement here to operate on each one separately.
if (uuid.equalsIgnoreCase(UuidRead)) {
Log.w(TAG, "Connection State: Read 2");
final int Val = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0);
broadCast(BROADCAST_ADDEDFrag, Val, "read_Service");
Log.i(TAG, "Connection State: onCharacteristicRead: " + Val);
Log.d(TAG, "Connection State Read state: "+Read);
readCharacteristic(gatt, mCharacterisitc2);
}
if (uuid.equalsIgnoreCase(UuidRead2)) {
Log.w(TAG, "Connection State: Read 3");
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
String msg = "letter: " + new String(data) + "\nHEX: " + stringBuilder.toString();
Log.d(TAG, "Connection State: onCharacteristicRead2: 4 " + msg);
broadCastHEX(BROADCAST_ADDEDFrag, msg, "read_Service2");
}
Read = false; //Has to be set to false in the last read message..
Log.d(TAG, "Connection State Read state: "+Read);
}
}
}
};
/**
* Runs service discovery on the connected device.
*
* #return
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void discoverServices() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.discoverServices();
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void Write(Integer integer) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "Connection State BluetoothAdapter not initialized");
return;
}
Integer Val = integer;
byte[] byteVal;
byteVal = intToByteArray(Val);
mCharacterisitcWrite.setValue(byteVal);
Log.d(TAG, "Connection State write 1: " + byteVal);
mBluetoothGatt.writeCharacteristic(mCharacterisitcWrite);
}
public static byte[] intToByteArray(int a) {
byte[] ret = new byte[4];
ret[3] = (byte) (a & 0xFF);
ret[2] = (byte) ((a >> 8) & 0xFF);
ret[1] = (byte) ((a >> 16) & 0xFF);
ret[0] = (byte) ((a >> 24) & 0xFF);
return ret;
}
/**
* This method is used to read the state of the LED from the device
*/
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void readCharacteristic(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || gatt == null) {
Log.w(TAG, "Connection State: BluetoothAdapter not initialized 2");
return;
}
Log.w(TAG, "Connection State: BluetoothAdapter initialized");
gatt.readCharacteristic(characteristic);
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
final int new_rssi = rssi;
if (rssi > signalStrength && device.getName() != null) {
mHandler.post(new Runnable() {
#Override
public void run() {
try {
FragmentBLE.addDevice(device, new_rssi);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
};
public void broadCast(String broadcastTXT, Integer Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
public void broadCastHEX(String broadcastTXT, String Val, String key) {
Log.d(TAG, "Connection State: -> broadCast: Service Broadcast");
Intent broadcastIntent = new Intent().putExtra(key, Val);
broadcastIntent.setAction(broadcastTXT);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
}
So what causes this error to occure?
looks like it's somthing to do with java.lang.RuntimeException: Unable to instantiate service com.example.wrd.ble.BLE_Service, and I've been serching on it, but can't seem to find anything that helps.
EDIT
So my filled contructer is done before my empty contructer is set. I bind in my onStart()
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
protected void onStart() {
super.onStart();
// Start the BLE Service
Log.d(TAG, "Starting BLE Service");
Intent gattServiceIntent = new Intent(this, BLE_Service.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
Log.d(TAG, "Bluetooth is Enabled");
registerReceiver(mBTStateUpdateReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
}
And then in my oncreate I run the following
mBTLeScanner = new BLE_Service(this, 7500, -75);
but somehow BLE_Service(this, 7500, -75) is finished before onStart()
Create an empty constructor.
BLE_Service(){
}
Trying this...
public class MainActivity extends Activity {
PendingIntent mPermissionIntent;
Button btnCheck;
TextView textInfo;
UsbDevice device;
UsbManager manager;
private static final String ACTION_USB_PERMISSION = "com.mobilemerit.usbhost.USB_PERMISSION";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnCheck = (Button) findViewById(R.id.check);
textInfo = (TextView) findViewById(R.id.info);
btnCheck.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
textInfo.setText("");
checkInfo();
}
});
}
public void startPrinting(final UsbDevice printerDevice) {
new Handler().post(new Runnable() {
UsbDeviceConnection conn;
UsbInterface usbInterface;
#Override
public void run() {
try {
Log.e("Info", "Bulk transfer started");
usbInterface = printerDevice.getInterface(0);
UsbEndpoint endPoint = usbInterface.getEndpoint(0);
conn = manager.openDevice(device);
conn.claimInterface(usbInterface, true);
String myStringData = "\nThis \nis \nmy \nsample \ntext";
byte[] array = myStringData.getBytes();
ByteBuffer output_buffer = ByteBuffer
.allocate(array.length);
UsbRequest request = new UsbRequest();
request.initialize(conn, endPoint);
request.queue(output_buffer, array.length);
if (conn.requestWait() == request) {
Log.i("Info", output_buffer.getChar(0) + "");
Message m = new Message();
m.obj = output_buffer.array();
// handler.sendMessage(m);
output_buffer.clear();
} else {
Log.e("Info", "No request recieved");
}
// int transfered = conn.bulkTransfer(endPoint,
// myStringData.getBytes(),
// myStringData.getBytes().length, 5000);
// Log.i("Info", "Amount of data transferred : " +
// transfered);
} catch (Exception e) {
Log.e("Exception", "Unable to transfer bulk data");
e.printStackTrace();
} finally {
try {
conn.releaseInterface(usbInterface);
Log.e("Info", "Interface released");
conn.close();
Log.e("Info", "Usb connection closed");
unregisterReceiver(mUsbReceiver);
Log.e("Info", "Brodcast reciever unregistered");
} catch (Exception e) {
Log.e("Exception",
"Unable to release resources because : "
+ e.getMessage());
e.printStackTrace();
}
}
}
});
}
private void checkInfo() {
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
/*
* this block required if you need to communicate to USB devices it's
* take permission to device
* if you want than you can set this to which device you want to communicate
*/
// ------------------------------------------------------------------
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
// -------------------------------------------------------------------
HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
String i = "";
while (deviceIterator.hasNext()) {
device = deviceIterator.next();
manager.requestPermission(device, mPermissionIntent);
i += "\n" + "DeviceID: " + device.getDeviceId() + "\n"
+ "DeviceName: " + device.getDeviceName() + "\n"
+ "DeviceClass: " + device.getDeviceClass() + " - "
+ "DeviceSubClass: " + device.getDeviceSubclass() + "\n"
+ "VendorID: " + device.getVendorId() + "\n"
+ "ProductID: " + device.getProductId() + "\n";
}
textInfo.setText(i);
if(!(i.equalsIgnoreCase("")))
{
startPrinting(device);
}
}
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbDevice device = (UsbDevice) intent
.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
if (device != null) {
// call method to set up device communication
}
} else {
Log.d("ERROR", "permission denied for device " + device);
}
}
}
}
};
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mUsbReceiver);
}
}
This code shows the device connected with OTG but Not Accepted as printer device to canon 2900b
Printer going in idle mode.
or phone got hanged
I'm trying to connect to random Bluetooth device that match a certain characteristic. I just want to print the incoming messages from the bluetooth device.
I've been trying for the past few days to try and connect to some random bluetooth device that matches a characteristic so that I'll be able to just print the messages from the bluetooth device.
public class main extends AppCompatActivity {
private List Service_UUIDs;
private List Charac_UUIDS;
private List Descriptor_UUIDs;
public static final UUID descriptor = UUID.fromString("863930fc-947c-421b-
9170-9969ea6ad610");
private BluetoothAdapter bluetoothAdapter = null;
private BluetoothLeScanner bluetoothLeScanner;
private ScanCallback scanCallback;
private TextView messageText;
private Handler handler;
private static final int SCAN_TIME = 15000;
private int connectionState = STATE_DISCONNECTED;
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTED = 2;
private boolean isConnected;
private boolean isScanning;
private BluetoothLeScanner myScanner;
private BluetoothGatt bluetoothGatt;
private String connected = "";
public List<BluetoothGattService> myServices;
private ScanCallback myScanCallBack;
private BluetoothDevice myDevice;
private HashMap<String, BluetoothDevice> myScanResults;
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public static final int REQUEST_ENABLE_BT = 10;
private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[])
null);
m.invoke(device, (Object[]) null);
Log.d("unpairDevice", Integer.toString(device.getBondState()));
}
catch (Exception e) { Log.e("unpairDevice", e.getMessage()); }
}
private void makeToast(String message) {
//creates pop-ups in UI of the message
Context context = getApplicationContext();
CharSequence text = message;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
}
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BluetoothManager bluetoothManager = (BluetoothManager)
getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
if(!bluetoothManager.getAdapter().isEnabled()){
Intent btEnable = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(btEnable, REQUEST_ENABLE_BT);
}
messageText = findViewById(R.id.atm_msg);
findViewById(R.id.scan_button).setOnClickListener(new handleScan());
}
class handleScan implements View.OnClickListener{
public void onClick(View view){
startScan();
}
}
private void startScan() {
List<ScanFilter> filters = new ArrayList<>();
ScanFilter scanFilter = new ScanFilter.Builder()
.setServiceUuid(new ParcelUuid(descriptor))
.build();
filters.add(scanFilter);
ScanSettings settings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_POWER)
.build();
myScanResults = new HashMap<>();
myScanCallBack = new BtleScanCallback(myScanResults);
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
bluetoothLeScanner.startScan(myScanCallBack);
isScanning = true;
new Handler().postDelayed(this::stopScan, SCAN_TIME);
}
private void stopScan(){
if(isScanning && bluetoothAdapter != null
&& bluetoothAdapter.isEnabled()
&& bluetoothLeScanner != null){
bluetoothLeScanner.stopScan(myScanCallBack);
scanComplete();
}
myScanCallBack = null;
isScanning = false;
handler = null;
}
private void scanComplete(){
if (myScanResults.isEmpty()){
return;
}
for(BluetoothDevice device: myScanResults.values()){
connectDevice(device);
}
}
protected class BtleScanCallback extends ScanCallback {
private HashMap<String, BluetoothDevice> myScanResults;
BtleScanCallback(HashMap<String, BluetoothDevice> scanResults) {
myScanResults = scanResults;
}
#Override
public void onScanResult(int callbackType, ScanResult result) {
addScanResult(result);
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
for (ScanResult result : results) {
addScanResult(result);
}
}
#Override
public void onScanFailed(int errorCode) {
makeToast("BLE Scan Failed with code " + errorCode);
}
private void addScanResult(ScanResult result) {
myDevice = result.getDevice();
String deviceAddress = myDevice.getAddress();
myScanResults.put(deviceAddress, myDevice);
}
}
private void connectDevice(BluetoothDevice device) {
bluetoothGatt = device.connectGatt(this, false, bluetoothGattCallback);
}
private final BluetoothGattCallback bluetoothGattCallback = new
BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int
newState) {
super.onConnectionStateChange(gatt, status, newState);
if (status == gatt.GATT_FAILURE){
Log.d("BLE_Assistance", "-----> status: " + gatt.GATT_FAILURE);
disconnectGattServer();
return;
}
if (status == 133){
bluetoothAdapter.disable();
bluetoothAdapter.enable();
Log.d("OCSC: ", "133 GATT_ERROR OCCURRED");
}
if (newState == gatt.STATE_CONNECTED){
Log.d("BLE_Assistance", "-----> state: " +
gatt.STATE_CONNECTED);
connectionState = gatt.STATE_CONNECTED;
isConnected = true;
return;
}
else if (status != gatt.GATT_SUCCESS){
Log.d("BLE_Assistance", "-----> status: could not connect");
disconnectGattServer();
return;
}
else if (newState == gatt.STATE_DISCONNECTED){
Log.d("BLE_Assistance", "status: " + gatt.STATE_DISCONNECTED);
disconnectGattServer();
}
}
public void disconnectGattServer(){
isConnected = false;
connected = "";
if (bluetoothLeScanner != null && scanCallback != null){
bluetoothLeScanner.flushPendingScanResults(scanCallback);
}
if (!myScanResults.isEmpty()){
myScanResults.clear();
}
try {
if (myServices.isEmpty()){
Log.d("Services", "Empty");
}
else{
myServices.clear();
}
} catch (NullPointerException nullPointerException){
Log.d("Services", "" + nullPointerException);
}
bluetoothAdapter.cancelDiscovery();
if(bluetoothGatt != null){
bluetoothGatt.abortReliableWrite();
bluetoothGatt.disconnect();
bluetoothGatt.close();
bluetoothGatt = null;
Log.d("disconnect server", ": Disconnected GATT Server");
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
byte[] msg_bytes = characteristic.getValue();
try {
String message = new String(msg_bytes, 0, msg_bytes.length,
"utf-8");
Log.d("onCharacteristicRead", message);
new Handler(Looper.getMainLooper()).postDelayed(() -> {
makeToast("onCharacteristicRead: " + message);
messageText.append("\nonCharacteristicRead: " + message);
}, 1000);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status){
super.onServicesDiscovered(gatt,status);
Service_UUIDs = new ArrayList();
Charac_UUIDS = new ArrayList();
Descriptor_UUIDs = new ArrayList();
if(status != gatt.GATT_SUCCESS){
return;
}else{
myServices = gatt.getServices();
for (BluetoothGattService service : myServices) {
for (BluetoothGattCharacteristic charac : service.getCharacteristics()) {
if (charac.getUuid().toString().contains("863930fc")) {
Service_UUIDs.add(charac.getService().getUuid().toString());
Charac_UUIDS.add(charac.getUuid().toString());
Descriptor_UUIDs.add(descriptor);
BluetoothGattDescriptor desc = charac.getDescriptor(descriptor);
gatt.setCharacteristicNotification(charac, true);
desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(desc);
}
}
}
Log.d("BLE_Assistance", "------ UUID Lists: " + Service_UUIDs + Charac_UUIDS + Descriptor_UUIDs);
}
}
};
}
I am not completely sure, I am also struggling with this kind of project right now and I am quite new to programming on Android. But I spotted a small mistake in your startScan and stopScan codes
bluetoothLeScanner.startScan(myScanCallBack);
Should be
bluetoothLeScanner.startScan(List<ScanFilter> filters, ScanSettings settings, ScanCallback callback)
with your scan filters and settings.
When you only send 'myScanCallback' to your 'bluetoothLeScanner.startScan', you're sending only default parameters with no filters.
https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,%20android.bluetooth.le.ScanCallback)
This means that you're searching for every device, and not specifically the one you want.
For testing while powerdraw isn't an issue, you can also set your ScanSettings to LOW_LATENCY (LOW_POWER is more intuitive to use with BLE but not a requirement. You can switch it later when you want more battery life while scanning).
I hope it helps you
I try to develop a minimalistic BluetoothChat for Android with Phonegap. The Plugin is based on the Android SDK Example of the BluetoothChat as you can see in the example code.
The native BluetoothChat works fine.
The Problem is, when i call my "write"-Function, the "ConnectedThread" is always null, although the connection is established.
I can't recognize where it is set to null again, after the State was set to 3 (STATE_CONNECTED).
So when i run the program native on android, it works fine and the state during write is always 3, but when i use my phonegap plugin 'r'(ConnectedThread) becomes null :
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
Log.i(TAG, "State "+mState);
if (mState != STATE_CONNECTED) return;
Log.i(TAG, "Connected Thread "+mConnectedThread);
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
I used a lot of debug messages, but i was never informed that the state is null again.
Full source code :
PLUGIN.java
public class BluetoothConnection extends CordovaPlugin {
//Android specific tag-messages
private static final String TAG ="BluetoothConnection";
private static final boolean D = true;
// Member-Variables
public BluetoothAdapter mBluetoothAdapter;
public JSONArray mListOfDiscoveredDevices;
public String mConnectedDeviceName;
public ConnectionHandler mConnectionHandler;
// Phonegap-specific actions, which call the function
public String ACTION_ENABLEBLUETOOTH = "enableBluetooth";
public String ACTION_DISABLEBLUETOOTH = "disableBluetooth";
public String ACTION_DISCOVERDECIVES = "discoverDevices";
public String ACTION_STOPDISCOVERDEVICES = "stopDiscoverDevices";
public String ACTION_CREATEBOND = "createBond";
public String ACTION_WRITEMESSAGE = "writeMessage";
// not usable, this moment
public String ACTION_DISCONNECT = "disconnect";
//Message types sent from the ConnectionHandler
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
#Override
public boolean execute(String action, JSONArray args,
CallbackContext callbackContext) throws JSONException {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter.equals(null)) {
Log.i(TAG, "no adapter was found");
}
mConnectionHandler = new ConnectionHandler(mHandler);
if (action.equals(ACTION_ENABLEBLUETOOTH)) {
enableBluetooth();
}
else if (action.equals(ACTION_DISABLEBLUETOOTH)) {
disableBluetooth();
}
else if (action.equals(ACTION_DISCOVERDECIVES)) {
discoverDevices();
}
else if (action.equals(ACTION_STOPDISCOVERDEVICES)) {
stopDiscovering(callbackContext);
}
else if (action.equals(ACTION_CREATEBOND)) {
try {
BluetoothDevice remoteBtDevice = createBond(args, callbackContext);
connect(remoteBtDevice, callbackContext);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if(action.equals(ACTION_WRITEMESSAGE)){
writeMessage(args.getString(0));
}
else if (action.equals(ACTION_DISCONNECT)) {
disconnect();
}
return false;
}
public void enableBluetooth() {
if (!mBluetoothAdapter.equals(null)) {
mBluetoothAdapter.enable();
Log.i(TAG, "bluetooth on");
}
}
public void disableBluetooth() {
if (mBluetoothAdapter.isEnabled()) {
mBluetoothAdapter.disable();
Log.i(TAG, "bluetooth off");
}
}
public void discoverDevices() {
mListOfDiscoveredDevices = new JSONArray();
Log.i("Log", "in the start searching method");
IntentFilter intentFilter = new IntentFilter(
BluetoothDevice.ACTION_FOUND);
cordova.getActivity().registerReceiver(mFoundDevices, intentFilter);
mBluetoothAdapter.startDiscovery();
}
private void stopDiscovering(CallbackContext callbackContext) {
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
PluginResult res = new PluginResult(PluginResult.Status.OK,
mListOfDiscoveredDevices);
res.setKeepCallback(true);
callbackContext.sendPluginResult(res);
Log.i("Info", "Stopped discovering Devices !");
}
public BluetoothDevice createBond(JSONArray args, CallbackContext callbackContext) throws Exception {
String macAddress = args.getString(0);
Log.i(TAG, "Connect to MacAddress "+macAddress);
BluetoothDevice btDevice = mBluetoothAdapter.getRemoteDevice(macAddress);
Log.i("Device","Device "+btDevice);
Class class1 = Class.forName("android.bluetooth.BluetoothDevice");
Method createBondMethod = class1.getMethod("createBond");
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
if(btDevice.equals(null))
throw new NullPointerException("Remote BluetoothDevice could not be paired !");
return btDevice;
}
public void removeBond(BluetoothDevice btDevice) throws Exception {
Class btClass = Class.forName("android.bluetooth.BluetoothDevice");
Method removeBondMethod = btClass.getMethod("removeBond");
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
}
public void connect(BluetoothDevice btDevice, CallbackContext callbackContext) {
if(!btDevice.equals(null)){
mConnectionHandler.connect(btDevice, false);
PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
result.setKeepCallback(true);
callbackContext.sendPluginResult(result);
Log.i(TAG, "Status after connecting "+mConnectionHandler.getState());
}
else {
callbackContext.error("Could not connect to "+btDevice.getAddress());
}
}
public void disconnect(){
}
public void writeMessage(String message){
if(mConnectionHandler.getState() != ConnectionHandler.STATE_CONNECTED){
Log.i(TAG, "Could not write to device");
Log.i(TAG, "State "+mConnectionHandler.getState());
}
if(message.length() > 0) {
byte[] send = message.getBytes();
mConnectionHandler.write(send);
Log.i(TAG, "sending "+message);
}
else {
Log.i(TAG, "There is nothing to send.");
}
}
private BroadcastReceiver mFoundDevices = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Message msg = Message.obtain();
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
Toast.makeText(context, "found Device !", Toast.LENGTH_SHORT).show();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i("FOUND", "Name " + device.getName() + "-" + device.getAddress());
JSONObject discoveredDevice = new JSONObject();
try {
discoveredDevice.put("name", device.getName());
discoveredDevice.put("adress", device.getAddress());
if (!isJSONInArray(discoveredDevice)) {
mListOfDiscoveredDevices.put(discoveredDevice);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
};
private final Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
switch (msg.arg1) {
case ConnectionHandler.STATE_CONNECTED:
Log.i(TAG, "ConnectionHandler.STATE_CONNECTED !");
break;
case ConnectionHandler.STATE_CONNECTING:
Log.i(TAG, "ConnectionHandler.STATE_CONNECTING !");
break;
case ConnectionHandler.STATE_LISTEN:
Log.i(TAG, "ConnectionHandler.STATE_LISTEN !");
break;
case ConnectionHandler.STATE_NONE:
Log.i(TAG, "ConnectionHandler.STATE_NONE !");
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
Log.i(TAG, "Write "+writeMessage);
break;
case MESSAGE_READ:
byte[] readBuf = (byte[]) msg.obj;
// construct a string from the valid bytes in the buffer
String readMessage = new String(readBuf, 0, msg.arg1);
Log.i(TAG, "Read "+readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Log.i(TAG, mConnectedDeviceName);
break;
case MESSAGE_TOAST:
String message = msg.getData().getString(TOAST);
Log.i(TAG, "Connection lost : " +message);
break;
}
}
};}
CONNECTION-HANDLER
public class ConnectionHandler {
// Debugging
private static final String TAG = "BluetoothChatService";
private static final boolean D = true;
// Name for the SDP record when creating server socket
private static final String NAME_SECURE = "BluetoothChatSecure";
private static final String NAME_INSECURE = "BluetoothChatInsecure";
// Unique UUID for this application
private static final UUID MY_UUID_SECURE =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static final UUID MY_UUID_INSECURE =
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private AcceptThread mSecureAcceptThread;
private AcceptThread mInsecureAcceptThread;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 3; // now connected to a remote device
public ConnectionHandler(Handler handler) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
}
private synchronized void setState(int state) {
if (D) Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
// Give the new state to the Handler so the UI Activity can update
mHandler.obtainMessage(BluetoothConnection.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
public synchronized int getState() {
return mState;
}
public synchronized void start() {
if (D) Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
setState(STATE_LISTEN);
// Start the thread to listen on a BluetoothServerSocket
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread(true);
mSecureAcceptThread.start();
}
if (mInsecureAcceptThread == null) {
mInsecureAcceptThread = new AcceptThread(false);
mInsecureAcceptThread.start();
}
}
public synchronized void connect(BluetoothDevice device, boolean secure) {
if (D) Log.d(TAG, "connect to: " + device);
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device, secure);
mConnectThread.start();
setState(STATE_CONNECTING);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device, final String socketType) {
if (D) Log.d(TAG, "connected, Socket Type:" + socketType);
// Cancel the thread that completed the connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
// Cancel the accept thread because we only want to connect to one device
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
Message msg = mHandler.obtainMessage(BluetoothConnection.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(BluetoothConnection.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
public synchronized void stop() {
if (D) Log.d(TAG, "stop");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
if (mInsecureAcceptThread != null) {
mInsecureAcceptThread.cancel();
mInsecureAcceptThread = null;
}
setState(STATE_NONE);
}
public void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
Log.i(TAG, "State "+mState);
if (mState != STATE_CONNECTED) return;
Log.i(TAG, "Connected Thread "+mConnectedThread);
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
private void connectionFailed() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BluetoothConnection.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothConnection.TOAST, "Unable to connect device");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
ConnectionHandler.this.start();
}
private void connectionLost() {
// Send a failure message back to the Activity
Message msg = mHandler.obtainMessage(BluetoothConnection.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(BluetoothConnection.TOAST, "Device connection was lost");
msg.setData(bundle);
mHandler.sendMessage(msg);
// Start the service over to restart listening mode
ConnectionHandler.this.start();
}
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
private String mSocketType;
public AcceptThread(boolean secure) {
BluetoothServerSocket tmp = null;
mSocketType = secure ? "Secure":"Insecure";
// Create a new listening server socket
try {
if (secure) {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
MY_UUID_SECURE);
} else {
tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
NAME_INSECURE, MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
}
mmServerSocket = tmp;
}
public void run() {
if (D) Log.d(TAG, "Socket Type: " + mSocketType +
"BEGIN mAcceptThread" + this);
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (ConnectionHandler.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice(),
mSocketType);
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
}
public void cancel() {
if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
}
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device, boolean secure) {
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = secure ? "Secure" : "Insecure";
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
if (secure) {
tmp = device.createRfcommSocketToServiceRecord(
MY_UUID_SECURE);
} else {
tmp = device.createInsecureRfcommSocketToServiceRecord(
MY_UUID_INSECURE);
}
} catch (IOException e) {
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() " + mSocketType +
" socket during connection failure", e2);
}
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (ConnectionHandler.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType) {
Log.d(TAG, "create ConnectedThread: " + socketType);
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(BluetoothConnection.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
// Start the service over to restart listening mode
ConnectionHandler.this.start();
break;
}
}
}
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(BluetoothConnection.MESSAGE_WRITE, -1, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}}
Thanks !!!
I implemented again in a new project - now it works, don't know why - but it work now.