I'm trying to send a characteristic in a BLE android to another device.
Seaching in internet I found some code that help me to do this, but I cant transmit successfully the data.
This is my code, based on Gatt android sample project:
public class DeviceControlActivity extends Activity {
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private TextView mConnectionState;
private TextView mDataField;
private TextView mRssiField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private BluetoothGattCharacteristic mWriteCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
BluetoothGattCharacteristic characteristic;
public BluetoothGatt mBluetoothGatt;
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e("Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
mBluetoothLeService.setBLEServiceCb(mDCServiceCb);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// If a given GATT characteristic is selected, check for supported features. This sample
// demonstrates 'Read' and 'Notify' features. See
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
// list of supported characteristic features.
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties();
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
Log.d("BluetoothGattCharacteristic has PROPERTY_READ, so send read request");
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERTY_NOTIFY, so send notify request");
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) |
(charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
mWriteCharacteristic = characteristic;
// popup an dialog to write something.
showCharactWriteDialog();
}
return true;
}
return false;
}
};
private void showCharactWriteDialog() {
DialogFragment newFrame = new BleCharacterDialogFragment();
newFrame.show(getFragmentManager(), "blewrite");
}
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
// Sets up UI references.
((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
mGattServicesList.setOnChildClickListener(servicesListClickListner);
mConnectionState = (TextView) findViewById(R.id.connection_state);
mDataField = (TextView) findViewById(R.id.data_value);
mRssiField = (TextView) findViewById(R.id.signal_rssi);
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
#Override
protected void onResume() {
super.onResume();
//registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d("Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
//unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
} else {
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
#TargetApi(Build.VERSION_CODES.ECLAIR)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private void displayRssi(String rssi) {
if (rssi != null) {
//Log.d("-- dispaly Rssi: " + rssi);
mRssiField.setText(rssi);
}
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void displayGattServices(List<BluetoothGattService> gattServices) {
Log.d("displayGATTServices");
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
this,
gattServiceData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 },
gattCharacteristicData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 }
);
mGattServicesList.setAdapter(gattServiceAdapter);
}
private DCServiceCb mDCServiceCb = new DCServiceCb();
public class DCServiceCb implements BluetoothLeService.BLEServiceCallback {
#Override
public void displayRssi(final int rssi) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayRssi(String.valueOf(rssi));
}
}
);
}
#Override
public void displayData(final String data) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayData(data);
}
});
}
#Override
public void notifyConnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
}
});
}
#Override
public void notifyDisconnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
}
});
}
#Override
public void displayGATTServices() {
Log.d("displayGATTServices.");
runOnUiThread(new Runnable() {
#Override
public void run() {
if (mBluetoothLeService != null) {
DeviceControlActivity.this.displayGattServices(
mBluetoothLeService.getSupportedGattServices());
}
}
});
}
}
#SuppressLint("ValidFragment")
public class BleCharacterDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.write_charact_dialog, container, false);
final EditText ed = (EditText) v.findViewById(R.id.charact_value);
Button ok = (Button) v.findViewById(R.id.dialog_confirm);
Button cancel = (Button) v.findViewById(R.id.dialog_cancel);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
characteristic.setValue(new byte[] {0x02});
writeCharacteristicValue(characteristic);
Toast.makeText(getApplicationContext(), "Se envĂo el dato",
Toast.LENGTH_SHORT).show();
dismiss();
return;
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
return v;
}
}
public void writeCharacteristicValue(BluetoothGattCharacteristic characteristica)
{
byte[] value= {(byte) 0xFF};
characteristica.setValue(bytesToHex(value));
boolean status = mBluetoothGatt.writeCharacteristic(characteristica);
}
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public String bytesToHex(byte[] bytes)
{
char[] hexChars = new char[bytes.length * 2];
int v;
for ( int j = 0; j < bytes.length; j++ )
{
v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
}
The idea is the user connect to the bluetooth and touch the last service. Then if enter a text and push OK, to write a characteristic in bluetooth device. But when I do that, appears a error that say:E/AndroidRuntime(17427): Process: com.example.ble, PID: 17427
E/AndroidRuntime(17427): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ble/com.example.ble.DeviceControlActivity}: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.ble.DeviceControlActivity$BleCharacterDialogFragment: make sure class name exists, is public, and has an empty constructor that is public
I dont have any experices working with BLE, then I dont understand many things about that.
If someone can help me to solve the problem or share a full code that do this.
Thanks for advance
Related
I wrote a code in which I am able to read a notify value from a hear rate sensor when it changes.
But I need also to read the battery level of the device, which is another service from the emulated device, but whenever I try to read the battery value, the first part don't even send the notify values from the heart rate.
Here is the code:
public class MainActivity extends AppCompatActivity {
BluetoothManager btManager;
BluetoothAdapter btAdapter;
BluetoothLeScanner btScanner;
Button startScanningButton;
Button stopScanningButton;
TextView peripheralTextView;
private final static int REQUEST_ENABLE_BT = 1;
private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;
Boolean btScanning = false;
int deviceIndex = 0;
ArrayList<BluetoothDevice> devicesDiscovered = new ArrayList<BluetoothDevice>();
EditText deviceIndexInput;
Button connectToDevice;
Button disconnectDevice;
BluetoothGatt bluetoothGatt;
UUID HEART_RATE_SERVICE_UUID = convertFromInteger(0x180D);
UUID HEART_RATE_MEASUREMENT_CHAR_UUID = convertFromInteger(0x2A37);
UUID HEART_RATE_CONTROL_POINT_CHAR_UUID = convertFromInteger(0x2A39);
UUID CLIENT_CHARACTERISTIC_CONFIG_UUID = convertFromInteger(0x2902);
UUID BATTERY_LEVEL = convertFromInteger(0x2A19);
UUID BATTERY_SERVICE = convertFromInteger(0x180F);
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
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 final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
public Map<String, String> uuids = new HashMap<String, String>();
// Stops scanning after 5 seconds.
private Handler mHandler = new Handler();
private static final long SCAN_PERIOD = 1000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
peripheralTextView = (TextView) findViewById(R.id.PeripheralTextView);
peripheralTextView.setMovementMethod(new ScrollingMovementMethod());
deviceIndexInput = (EditText) findViewById(R.id.InputIndex);
deviceIndexInput.setText("0");
connectToDevice = (Button) findViewById(R.id.ConnectButton);
connectToDevice.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
connectToDeviceSelected();
}
});
disconnectDevice = (Button) findViewById(R.id.DisconnectButton);
disconnectDevice.setVisibility(View.INVISIBLE);
disconnectDevice.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
disconnectDeviceSelected();
}
});
startScanningButton = (Button) findViewById(R.id.StartScanButton);
startScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startScanning();
}
});
stopScanningButton = (Button) findViewById(R.id.StopScanButton);
stopScanningButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopScanning();
}
});
stopScanningButton.setVisibility(View.INVISIBLE);
btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
btAdapter = btManager.getAdapter();
btScanner = btAdapter.getBluetoothLeScanner();
if (btAdapter != null && !btAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
}
// Make sure we have access coarse location enabled, if not, prompt the user to enable it
/* if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect peripherals.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
});
builder.show();
}*/
//client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
// Device scan callback.
private ScanCallback leScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
peripheralTextView.append("Index: " + deviceIndex + ", Device Name: " + result.getDevice().getName() + " rssi: " + result.getRssi() + ", MAC: " + result.getDevice().getAddress() + "\n");
devicesDiscovered.add(result.getDevice());
deviceIndex++;
// auto scroll for text view
final int scrollAmount = peripheralTextView.getLayout().getLineTop(peripheralTextView.getLineCount()) - peripheralTextView.getHeight();
// if there is no need to scroll, scrollAmount will be <=0
if (scrollAmount > 0) {
peripheralTextView.scrollTo(0, scrollAmount);
}
}
};
// Device connect call back
private final BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
// this will get called anytime you perform a read or write characteristic operation
final byte[] teste = characteristic.getValue();
final String batida = teste.toString();
final String result = "result";
int format = BluetoothGattCharacteristic.FORMAT_UINT8;
final int heartRate = characteristic.getIntValue(format, 1);
String TAG = "d";
Log.d(TAG, String.format("Received heart rate: %d", heartRate));
Log.v(result , batida);
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("value of sensor (BPM) "+ heartRate + "\n");
}
});
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
// this will get called when a device connects or disconnects
System.out.println(newState);
switch (newState) {
case 0:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("device disconnected\n");
connectToDevice.setVisibility(View.VISIBLE);
disconnectDevice.setVisibility(View.INVISIBLE);
}
});
break;
case 2:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("device connected\n");
connectToDevice.setVisibility(View.INVISIBLE);
disconnectDevice.setVisibility(View.VISIBLE);
}
});
// discover services and characteristics for this device
bluetoothGatt.discoverServices();
break;
default:
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("we encounterned an unknown state, uh oh\n");
}
});
break;
}
}
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
// this will get called after the client initiates a BluetoothGatt.discoverServices() call
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("device services have been discovered\n");
}
});
displayGattServices(bluetoothGatt.getServices());
BluetoothGattCharacteristic characteristic = gatt.getService(HEART_RATE_SERVICE_UUID).getCharacteristic(HEART_RATE_MEASUREMENT_CHAR_UUID);
//BluetoothGattCharacteristic battery = gatt.getService(BATTERY_SERVICE).getCharacteristic(BATTERY_LEVEL);
//gatt.readCharacteristic(battery);
gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
BluetoothGattCharacteristic characteristic = gatt.getService(HEART_RATE_SERVICE_UUID).getCharacteristic(HEART_RATE_CONTROL_POINT_CHAR_UUID);
characteristic.setValue(new byte[]{1,1});
gatt.writeCharacteristic(characteristic);
}
#Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
};
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
System.out.println(characteristic.getUuid());
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_COARSE_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
System.out.println("coarse location permission granted");
} else {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Functionality limited");
builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
}
});
builder.show();
}
return;
}
}
}
public void startScanning() {
System.out.println("start scanning");
btScanning = true;
deviceIndex = 0;
devicesDiscovered.clear();
peripheralTextView.setText("");
peripheralTextView.append("Started Scanning\n");
startScanningButton.setVisibility(View.INVISIBLE);
stopScanningButton.setVisibility(View.VISIBLE);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
btScanner.startScan(leScanCallback);
}
});
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
stopScanning();
}
}, SCAN_PERIOD);
}
public void stopScanning() {
System.out.println("stopping scanning");
peripheralTextView.append("Stopped Scanning\n");
btScanning = false;
startScanningButton.setVisibility(View.VISIBLE);
stopScanningButton.setVisibility(View.INVISIBLE);
AsyncTask.execute(new Runnable() {
#Override
public void run() {
btScanner.stopScan(leScanCallback);
}
});
}
public void connectToDeviceSelected() {
peripheralTextView.append("Trying to connect to device at index: " + deviceIndexInput.getText() + "\n");
int deviceSelected = Integer.parseInt(deviceIndexInput.getText().toString());
bluetoothGatt = devicesDiscovered.get(deviceSelected).connectGatt(this, false, btleGattCallback);
}
public void disconnectDeviceSelected() {
peripheralTextView.append("Disconnecting from device\n");
bluetoothGatt.disconnect();
}
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
final String uuid = gattService.getUuid().toString();
System.out.println("Service discovered: " + uuid);
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("Service disovered: "+uuid+"\n");
}
});
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic :
gattCharacteristics) {
final String charUuid = gattCharacteristic.getUuid().toString();
System.out.println("Characteristic discovered for service: " + charUuid);
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
peripheralTextView.append("Characteristic discovered for service: "+charUuid+"\n");
}
});
}
}
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onStop() {
super.onStop();
}
public UUID convertFromInteger(int i) {
final long MSB = 0x0000000000001000L;
final long LSB = 0x800000805f9b34fbL;
long value = i & 0xFFFFFFFF;
return new UUID(MSB | (value << 32), LSB);
}
}
How can I read without interrupting the notify from BLE?
As you've observed, you can't start these two operations simultaneously (the first one will be overwritten and never executes):
gatt.readCharacteristic(battery);
gatt.writeDescriptor(descriptor);
Instead, you have to do the first operation, wait for it to finish (in your example, by waiting for onCharacteristicRead to be called), and then start the second operation. A common way to implement this is to use a queue to store pending operations, then pop items off the front of the queue and execute them one at a time in the rest of your code.
This required queuing is an annoying aspect of the Android BLE APIs that is not described in the documentation. For more details, check out my talk or list of resources for Android BLE.
I used the BluetoothLeGatt example code to write an app that automatically connects to a bonded BLE peripheral upon launching the app. Now i am trying to display the data from one of the peripheral's characteristic in a textView. The BluetoothLeGatt example code only demonstrates this using ExpandableListView.OnChildClickListener, my app should require no user input and simply get he data from the characteristic. This is what i have so far:
private TextView mConnectionState;
private TextView mDataField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// Handles various events fired by the Service.
// ACTION_GATT_CONNECTED: connected to a GATT server.
// ACTION_GATT_DISCONNECTED: disconnected from a GATT server.
// ACTION_GATT_SERVICES_DISCOVERED: discovered GATT services.
// ACTION_DATA_AVAILABLE: received data from the device. This can be a result of read
// or notification operations.
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
mConnectionState.setTextColor(Color.parseColor("#FF17AA00"));
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// Show all the supported services and characteristics on the user interface.
//displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_control);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
mConnectionState = (TextView) findViewById(R.id.connection_state);
mDataField = (TextView) findViewById(R.id.data);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
Figured it out.
Iterated through the services, then the characteristics after services were discovered.
UUID chara = UUID.fromString("c97433f0-be8f-4dc8-b6f0-5343e6100eb4");
List<BluetoothGattService> servs = mBluetoothLeService.getSupportedGattServices();
for (int i = 0; servs.size() > i; i++) {
List<BluetoothGattCharacteristic> charac = servs.get(i).getCharacteristics();
for (int j = 0; charac.size() > i; i++) {
BluetoothGattCharacteristic ch = charac.get(i);
if (ch.getUuid() == chara) {
mBluetoothLeService.readCharacteristic(ch);
mBluetoothLeService.setCharacteristicNotification(ch, true);
}
}
}
I am using some of the samples provided on line which show how to write to a device. What i want to do is as it loads up the device services and characteristics the app writes data to the tag, rather than open up a dialog to do this.
Can anyone shed some light on this please as i am new to Android development.
I have tried to add edit the code within the following section...
private void displayGattServices(List<BluetoothGattService> gattServices) {
but this line causes the app to crash...
byte[] bytes = DeviceControlActivity.this.mWriteCharacteristic.getValue();
As i tried to move the write part of the code from
public class BleCharacterDialogFragment extends DialogFragment
as i thought that would write to the BLE device.
All help is much appreciated, thanks. Below is the code i have. It came from https://github.com/suzp1984/Light_BLE originally.
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.PendingIntent;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
//import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import tkr.lightble.utils.Log;
/**
* For a given BLE device, this Activity provides the user interface to connect, display data,
* and display GATT services and characteristics supported by the device. The Activity
* communicates with {#code BluetoothLeService}, which in turn interacts with the
* Bluetooth LE API.
*/
public class DeviceControlActivity extends Activity {
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private TextView mConnectionState;
private TextView mDataField;
private TextView mRssiField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private BluetoothGattCharacteristic mWriteCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e("Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
mBluetoothLeService.setBLEServiceCb(mDCServiceCb);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// If a given GATT characteristic is selected, check for supported features. This sample
// demonstrates 'Read' and 'Notify' features. See
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
// list of supported characteristic features.
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties();
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
Log.d("BluetoothGattCharacteristic has PROPERTY_READ, so send read request");
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERTY_NOTIFY, so send notify request");
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) |
(charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
mWriteCharacteristic = characteristic;
// popup an dialog to write something.
showCharactWriteDialog();
}
return true;
}
return false;
}
};
private void showCharactWriteDialog() {
DialogFragment newFrame = new BleCharacterDialogFragment();
newFrame.show(getFragmentManager(), "blewrite");
}
private void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothLeService != null) {
mBluetoothLeService.writeCharacteristic(characteristic);
}
}
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
// Sets up UI references.
((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
mGattServicesList.setOnChildClickListener(servicesListClickListner);
mConnectionState = (TextView) findViewById(R.id.connection_state);
mDataField = (TextView) findViewById(R.id.data_value);
mRssiField = (TextView) findViewById(R.id.signal_rssi);
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
#Override
protected void onResume() {
super.onResume();
//registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d("Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
//unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
} else {
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
#TargetApi(Build.VERSION_CODES.ECLAIR)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private void displayRssi(String rssi) {
if (rssi != null) {
//Log.d("-- dispaly Rssi: " + rssi);
mRssiField.setText(rssi);
}
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void displayGattServices(List<BluetoothGattService> gattServices) {
Log.d("displayGATTServices");
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
this,
gattServiceData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 },
gattCharacteristicData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 }
);
mGattServicesList.setAdapter(gattServiceAdapter);
}
private DCServiceCb mDCServiceCb = new DCServiceCb();
public class DCServiceCb implements BluetoothLeService.BLEServiceCallback {
#Override
public void displayRssi(final int rssi) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayRssi(String.valueOf(rssi));
}
}
);
}
#Override
public void displayData(final String data) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayData(data);
}
});
}
#Override
public void notifyConnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
}
});
}
#Override
public void notifyDisconnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
}
});
}
#Override
public void displayGATTServices() {
Log.d("displayGATTServices.");
runOnUiThread(new Runnable() {
#Override
public void run() {
if (mBluetoothLeService != null) {
DeviceControlActivity.this.displayGattServices(
mBluetoothLeService.getSupportedGattServices());
}
}
});
}
}
public class BleCharacterDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.write_charact_dialog, container, false);
final EditText ed = (EditText) v.findViewById(R.id.charact_value);
Button ok = (Button) v.findViewById(R.id.dialog_confirm);
Button cancel = (Button) v.findViewById(R.id.dialog_cancel);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// write characterist here.
String str = ed.getText().toString();
//mWriteCharactristc.
byte[] strBytes = str.getBytes();
byte[] bytes;
bytes = DeviceControlActivity.this.mWriteCharacteristic.getValue();
//mWriteCharacteristic.
if (strBytes == null) {
Log.w("Cannot get Value from EditText Widget");
dismiss();
return;
}
if (bytes == null) {
// maybe just write a byte into GATT
Log.w("Cannot get Values from mWriteCharacteristic.");
dismiss();
return;
} else if (bytes.length <= strBytes.length) {
for(int i = 0; i < bytes.length; i++) {
bytes[i] = strBytes[i];
}
} else {
for (int i = 0; i < strBytes.length; i++) {
bytes[i] = strBytes[i];
}
}
DeviceControlActivity.this.mWriteCharacteristic.setValue(bytes);
DeviceControlActivity.this.writeCharacteristic(
DeviceControlActivity.this.mWriteCharacteristic
);
dismiss();
return;
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
return v;
}
}
}
To write a value to a device you have to know tow things
1-Service UUID
2-Characteristic UUID
You can read/write a value from/to Characteristic UUID
Here is the sample code to write a value to Characteristic.
public void writeCharacteristic(byte[] value)
{
BluetoothGattService service = mBluetoothGatt.getService(YOUR_SEVICE_UUID);
if (service == null) {
System.out.println("service null"); return;
}
BluetoothGattCharacteristic characteristic = service.getCharacteristic(YOUR_CHARACTERISTIC_UUID);
if (characteristic == null) {
System.out.println("characteristic null"); return;
}
characteristic.setValue(value);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
System.out.println("Write Status: " + status);
}
how to add small circle like pop up menu(like it rolls and display text connecting )when after moving to that particular item it should display connected/disconnected(when connected)successfully.now following is my devicescan activity.in this i will get list of all ble devices. here is my devicescanactivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActionBar().setTitle("BLE Devices");
UUIDS=new UUID[]{(UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb")) };
mHandler = new Handler();
db = new DataBaseAdapter(this);
// Use this check to determine whether BLE is supported on the device. Then you can
// selectively disable BLE-related features.
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
// Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
// BluetoothAdapter through BluetoothManager.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
// Checks if Bluetooth is supported on the device.
if (mBluetoothAdapter == null) {
finish();
return;
}
}
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onResume() {
super.onResume();
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
// Initializes list view adapter.
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// User chose not to enable Bluetooth.
if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
protected void onPause() {
super.onPause();
scanLeDevice(false);
mLeDeviceListAdapter.clear();
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
UUI D deviceUuid = new UUID(device.hashCode(), ((long)device.hashCode() << 32) );
String deviceUUID = deviceUuid.toString();
db.open();
Cursor c;
c=db.getData();
while (c != null && c.moveToNext())
{
if(deviceUUID.equalsIgnoreCase(c.getString(c.getColumnIndex("uuid"))))
{
sname = c.getString(c.getColumnIndex("devicename"));
sLight= c.getString(c.getColumnIndex("light"));
sAlarm= c.getString(c.getColumnIndex("alarm"));
}
else{
}
}
db.close();
Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, sname);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS,device.getAddress());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_UUID, deviceUUID);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_LIGHT, sLight);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ALARM, sAlarm);
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
}
startActivityForResult(intent, 0);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
private ArrayList<BluetoothDevice> mLeDevices;
private LayoutInflater mInflator;
public LeDeviceListAdapter() {
super();
mLeDevices = new ArrayList<BluetoothDevice>();
mInflator = DeviceScanActivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device) {
if(!mLeDevices.contains(device)&& device.getName().startsWith("BRV")) {
mLeDevices.add(device);
}
}
public BluetoothDevice getDevice(int position) {
return mLeDevices.get(position);
}
public void clear() {
mLeDevices.clear();
}
#Override
public int getCount() {
return mLeDevices.size();
}
#Override
public Object getItem(int i) {
return mLeDevices.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
// General ListView optimization code.
if (view == null) {
view = mInflator.inflate(R.layout.listitem_device, null);
viewHolder = new ViewHolder();
viewHolder.deviceAddress = (TextView)
view.findViewById(R.id.device_address);
viewHolder.deviceName = (TextView) view.findViewById(R.id.device_name);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
BluetoothDevice device = mLeDevices.get(i);
String deviceName = device.getName();
UUID deviceUuid = new UUID(device.hashCode(), ((long)device.hashCode() << 32));
String deviceId = deviceUuid.toString();
if (deviceName != null && deviceName.length() > 0){
db.open();
if(db!=null)
{
Cursor c;
c=db.getData();
String selectQuery = "SELECT * FROM DeviceDetails";
c = db.select(selectQuery);
while (c != null && c.moveToNext())
{
if (c.moveToFirst()) {
do {
if(deviceId.equalsIgnoreCase(c.getString(c.getColumnIndex("uuid"))))
{
viewHolder.deviceName.setText(c.getString(c.getColumnIndex("devicename")));
}
} while (c.moveToNext());
}
else {
viewHolder.deviceName.setText("noname");
}
}
}
db.close();
}
else
viewHolder.deviceName.setText("unknown_device");
viewHolder.deviceAddress.setText(device.getAddress());
return view;
}
}
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try{
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();}
catch(Exception e){
}
}
});
}
};
//Scanning for a particualr UUID
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback_particular =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
static class ViewHolder {
TextView deviceName;
TextView deviceAddress;
}
and from this class when i click item it moves to the devicecontrol activity so it is as follows.when i click it should moves to the devicecontrol activity and it should popup small menu like circle in it and display text like connecting.and after connnecting it was successful.
private final ServiceConnection mServiceConnection = new ServiceConnection()
{
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
create_alert();
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
Log.e(TAG, "Services Discovered");
check_forservices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}
}
};
private BluetoothLeService mBluetoothGatt;
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
........
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG,"In resume");
boolean result = false;
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
result = mBluetoothLeService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
try{
}catch(Exception e){
e.printStackTrace();
}
}
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
}
});
}
private void displayData(String data) {
Log.d("No serives",data );
if (data != null) {
battery.setText(data);
}
}
//Check for LEUCP servie
private void check_forservices(List<BluetoothGattService> gattServices){
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString =getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
Log.d("Service UUID::",uuid);
if(uuid.equalsIgnoreCase(SampleGattAttributes.SIMPLE_KEYS_SERVICE)){
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(LIST_NAME,SampleGattAttributes.lookup(uuid,unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
int charrec=gattCharacteristic.getProperties();
if ((charrec | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
Log.d("characterisitc UUID::",uuid+"....."+SampleGattAttributes.PORT1_CHARACTERSITIC);
if(uuid.equalsIgnoreCase(SampleGattAttributes.PORT1_CHARACTERSITIC.toString())){
check_port_1=1;
if(port1.isChecked())
{
}
}
else if(uuid.equalsIgnoreCase(SampleGattAttributes.PORT2_CHARACTERSITIC.toString())){
check_port_2=1;
if(port1.isChecked())
{
}
}
else if(uuid.equalsIgnoreCase(SampleGattAttributes.FINDME_CHARACTERSITIC.toString())){
find_me=1;
}
}
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
if(uuid.equalsIgnoreCase(SampleGattAttributes.BATTERY_SERVICE)){
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
int charrec=gattCharacteristic.getProperties();
if(uuid.equalsIgnoreCase(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG_BATTERY)){
Log.d("Matching battery %","");
char_write=uuid;
byte[] values={2,1,0,7,0,0,0};
if ((charrec | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(gattCharacteristic);
}
if ((charrec | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = gattCharacteristic;
mBluetoothLeService.setCharacteristicNotification(gattCharacteristic, true);
}
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
DeviceControlActivity.this);
// set title
alertDialogBuilder.setTitle(" Service has charactersitic:"+charrec);
// set dialog message
alertDialogBuilder.setMessage("Click yes to exit!").setCancelable(false).setPositiveButton("Yes",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int id) {
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
}
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
}
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
private void displayGattServices(List<BluetoothGattService> gattServices) {
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
if(uuid.equals(SampleGattAttributes.BATTERY_SERVICE)){
char_write=uuid;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
DeviceControlActivity.this);
alertDialogBuilder.setTitle("Battery Service has charactersitic:"+char_write);
alertDialogBuilder
.setMessage("Click yes to exit!")
.setCancelable(false)
.setPositiveButton("Yes",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int id) {
DeviceControlActivity.this.finish();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
this,
gattServiceData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 },
gattCharacteristicData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 }
);
mGattServicesList.setAdapter(gattServiceAdapter);
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
#Override
public void onContentChanged()
{
super.onContentChanged();
}
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
}
public void create_alert(){
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
DeviceControlActivity.this);
// set title
alertDialogBuilder.setTitle("Alert");
// set dialog message
alertDialogBuilder
.setMessage("The connection to device was lost. Please reconnect in the device settings menu.")
.setCancelable(false)
.setPositiveButton("Ok",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog,int id) {
finish();
}
}
)
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_connect:
progressDialog = ProgressDialog.show(DeviceControlActivity.this, "", "Connecting...");
new Thread() {
#Override
public void run() {
try{
mBluetoothLeService.connect(mDeviceAddress);
sleep(20000);
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
progressDialog.dismiss();
}
}.start();
// Toast.makeText(DeviceControlActivity.this,"Connecting...", Toast.LENGTH_LONG).show();
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 0 && resultCode == RESULT_OK) {
String position = data.getStringExtra("Daddress");
String newName = data.getStringExtra("Dname");
String newlight = data.getStringExtra("Dlight");
String newalarm = data.getStringExtra("Dalarm");
title_text.setText(newName);
mDeviceName=newName;
mDeviceLight=newlight;
mDeviceAlarm=newalarm;
}
if (requestCode == 1 && resultCode == Activity.RESULT_CANCELED) {
finish();
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
Have a look at Crouton. You can apply styles to it, i.e. make it round popup with text.
I am new to android programming,I got a chance to work with (wifi printers).In my application I have a pdf file which needs to be taken a printout by using wifi printer
I didnt have much idea on this,but after doing a research I got that,there are 3 things to be done for doing this
1)getting the list of devices which are connected to wifi network which my mobile is using right now.
2) Then,select a device and make a connection with that device.
3) Transfer data to a printer
I hope these are the steps which I need to use.
I worked on first point,but I am getting the (Wifi networks like Tata communications,vonline etc) but not the devices which are connecting to that networks.
Here is the code I used.........
public class WiFiDemo extends Activity implements OnClickListener
{
WifiManager wifi;
ListView lv;
TextView textStatus;
Button buttonScan;
int size = 0;
List<ScanResult> results;
String ITEM_KEY = "key";
ArrayList<HashMap<String, String>> arraylist = new ArrayList<HashMap<String, String>>();
SimpleAdapter adapter;
/* Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// textStatus = (TextView) findViewById(R.id.textStatus);
buttonScan = (Button) findViewById(R.id.buttonScan);
buttonScan.setOnClickListener(this);
lv = (ListView)findViewById(R.id.list);
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled() == false)
{
Toast.makeText(getApplicationContext(), "wifi is disabled..making it enabled", Toast.LENGTH_LONG).show();
wifi.setWifiEnabled(true);
}
this.adapter = new SimpleAdapter(WiFiDemo.this, arraylist, R.layout.row, new String[] { ITEM_KEY }, new int[] { R.id.list_value });
lv.setAdapter(this.adapter);
registerReceiver(new BroadcastReceiver()
{
#Override
public void onReceive(Context c, Intent intent)
{
results = wifi.getScanResults();
size = results.size();
}
}, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
}
public void onClick(View view)
{
arraylist.clear();
wifi.startScan();
checkWifi();
Toast.makeText(this, "Scanning...." + size, Toast.LENGTH_SHORT).show();
try
{
size = size - 1;
while (size >= 0)
{
HashMap<String, String> item = new HashMap<String, String>();
item.put(ITEM_KEY, results.get(size).SSID + " " + results.get(size).capabilities);
arraylist.add(item);
size--;
adapter.notifyDataSetChanged();
}
}
catch (Exception e)
{ }
}
private void checkWifi(){
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
final WifiManager wifiManager =
(WifiManager)this.getSystemService(Context.WIFI_SERVICE);;
registerReceiver(new BroadcastReceiver(){
#Override
public void onReceive(Context arg0, Intent arg1) {
// TODO Auto-generated method stub
Log.d("wifi","Open Wifimanager");
String scanList = wifiManager.getScanResults().toString();
Log.d("wifi","Scan:"+scanList);
}
},filter);
wifiManager.startScan();
}
}
please suggest for the solution
Thanks in advance friends
Refer this Android-wifi-print - Github, Which contains a demo application I created for the same.
Edit :
As #NileshThakkar said. we may lost connection to that link in future so, I am posting code here.. with flow.
checks connectivity.
If connected in WiFi.. am storing that WiFi configuration.
Now checking whether I already have printer's information (WiFi configuration of WiFi printer) is available or not. If available, I'll scan and get list of WiFi ScanResults and connects to that else.. It'll showing list of WiFi and clicking on that, user will connect to printer and stores that WiFi configuration for future printing jobs.
After print job completes, I'm connecting to my previous WiFi or Mobile data connection.
Now going back to 2nd step.
If user connected in Mobile data, I'm just enabling WiFi and following 3rd step.
After Print job completes, I'm just disabling WiFi. so that, We'll be connected back to Mobile data connection. (That is android default).
Libraries : gson-2.2.4, itextpdf-5.4.3
MyActivity.java
public class MyActivity extends Activity implements PrintCompleteService {
private Button mBtnPrint;
private WifiConfiguration mPrinterConfiguration, mOldWifiConfiguration;
private WifiManager mWifiManager;
private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
private WifiScanner mWifiScanner;
private PrintManager mPrintManager;
private List<PrintJob> mPrintJobs;
private PrintJob mCurrentPrintJob;
private File pdfFile;
private String externalStorageDirectory;
private Handler mPrintStartHandler = new Handler();
private Handler mPrintCompleteHandler = new Handler();
private String connectionInfo;
private boolean isMobileDataConnection = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
externalStorageDirectory = Environment.getExternalStorageDirectory().toString();
File folder = new File(externalStorageDirectory, Constants.CONTROLLER_RX_PDF_FOLDER);
pdfFile = new File(folder, "Print_testing.pdf");
} catch (Exception e) {
e.printStackTrace();
}
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mWifiScanner = new WifiScanner();
mBtnPrint = (Button) findViewById(R.id.btnPrint);
mBtnPrint.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
connectionInfo = Util.connectionInfo(MyActivity.this);
if (connectionInfo.equalsIgnoreCase(Constants.CONTROLLER_MOBILE)) {
isMobileDataConnection = true;
if (mWifiManager.isWifiEnabled() == false) {
Toast.makeText(getApplicationContext(), "Enabling WiFi..", Toast.LENGTH_LONG).show();
mWifiManager.setWifiEnabled(true);
}
mWifiManager.startScan();
printerConfiguration();
} else if (connectionInfo.equalsIgnoreCase(Constants.CONTROLLER_WIFI)) {
Util.storeCurrentWiFiConfiguration(MyActivity.this);
printerConfiguration();
} else {
Toast.makeText(MyActivity.this, "Please connect to Internet", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
protected void onResume() {
super.onResume();
try {
registerReceiver(mWifiScanner, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
try {
unregisterReceiver(mWifiScanner);
} catch (Exception e) {
e.printStackTrace();
}
}
private void printerConfiguration() {
mPrinterConfiguration = Util.getWifiConfiguration(MyActivity.this, Constants.CONTROLLER_PRINTER);
if (mPrinterConfiguration == null) {
showWifiListActivity(Constants.REQUEST_CODE_PRINTER);
} else {
boolean isPrinterAvailable = false;
mWifiManager.startScan();
for (int i = 0; i < mScanResults.size(); i++) {
if (mPrinterConfiguration.SSID.equals("\"" + mScanResults.get(i).SSID + "\"")) {
isPrinterAvailable = true;
break;
}
}
if (isPrinterAvailable) {
connectToWifi(mPrinterConfiguration);
doPrint();
} else {
showWifiListActivity(Constants.REQUEST_CODE_PRINTER);
}
}
}
private void connectToWifi(WifiConfiguration mWifiConfiguration) {
mWifiManager.enableNetwork(mWifiConfiguration.networkId, true);
}
private void showWifiListActivity(int requestCode) {
Intent iWifi = new Intent(this, WifiListActivity.class);
startActivityForResult(iWifi, requestCode);
}
#Override
public void onMessage(int status) {
mPrintJobs = mPrintManager.getPrintJobs();
mPrintCompleteHandler.postDelayed(new Runnable() {
#Override
public void run() {
mPrintCompleteHandler.postDelayed(this, 2000);
if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_COMPLETED) {
for (int i = 0; i < mPrintJobs.size(); i++) {
if (mPrintJobs.get(i).getId() == mCurrentPrintJob.getId()) {
mPrintJobs.remove(i);
}
}
switchConnection();
mPrintCompleteHandler.removeCallbacksAndMessages(null);
} else if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_FAILED) {
switchConnection();
Toast.makeText(MyActivity.this, "Print Failed!", Toast.LENGTH_LONG).show();
mPrintCompleteHandler.removeCallbacksAndMessages(null);
} else if (mCurrentPrintJob.getInfo().getState() == PrintJobInfo.STATE_CANCELED) {
switchConnection();
Toast.makeText(MyActivity.this, "Print Cancelled!", Toast.LENGTH_LONG).show();
mPrintCompleteHandler.removeCallbacksAndMessages(null);
}
}
}, 2000);
}
public void switchConnection() {
if (!isMobileDataConnection) {
mOldWifiConfiguration = Util.getWifiConfiguration(MyActivity.this, Constants.CONTROLLER_WIFI);
boolean isWifiAvailable = false;
mWifiManager.startScan();
for (int i = 0; i < mScanResults.size(); i++) {
if (mOldWifiConfiguration.SSID.equals("\"" + mScanResults.get(i).SSID + "\"")) {
isWifiAvailable = true;
break;
}
}
if (isWifiAvailable) {
connectToWifi(mOldWifiConfiguration);
} else {
showWifiListActivity(Constants.REQUEST_CODE_WIFI);
}
} else {
mWifiManager.setWifiEnabled(false);
}
}
public void printDocument(File pdfFile) {
mPrintManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
String jobName = getString(R.string.app_name) + " Document";
mCurrentPrintJob = mPrintManager.print(jobName, new PrintServicesAdapter(MyActivity.this, pdfFile), null);
}
public void doPrint() {
mPrintStartHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d("PrinterConnection Status", "" + mPrinterConfiguration.status);
mPrintStartHandler.postDelayed(this, 3000);
if (mPrinterConfiguration.status == WifiConfiguration.Status.CURRENT) {
if (Util.computePDFPageCount(pdfFile) > 0) {
printDocument(pdfFile);
} else {
Toast.makeText(MyActivity.this, "Can't print, Page count is zero.", Toast.LENGTH_LONG).show();
}
mPrintStartHandler.removeCallbacksAndMessages(null);
} else if (mPrinterConfiguration.status == WifiConfiguration.Status.DISABLED) {
Toast.makeText(MyActivity.this, "Failed to connect to printer!.", Toast.LENGTH_LONG).show();
mPrintStartHandler.removeCallbacksAndMessages(null);
}
}
}, 3000);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.REQUEST_CODE_PRINTER && resultCode == Constants.RESULT_CODE_PRINTER) {
mPrinterConfiguration = Util.getWifiConfiguration(MyActivity.this, Constants.CONTROLLER_PRINTER);
doPrint();
}
}
public class WifiScanner extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
mScanResults = mWifiManager.getScanResults();
Log.e("scan result size", "" + mScanResults.size());
}
}
}
WiFiListActivity.java
public class WifiListActivity extends Activity implements View.OnClickListener {
private ListView mListWifi;
private Button mBtnScan;
private WifiManager mWifiManager;
private WifiAdapter adapter;
private WifiListener mWifiListener;
private List<ScanResult> mScanResults = new ArrayList<ScanResult>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wifi_list);
mBtnScan = (Button) findViewById(R.id.btnNext);
mBtnScan.setOnClickListener(this);
mListWifi = (ListView) findViewById(R.id.wifiList);
mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (mWifiManager.isWifiEnabled() == false) {
Toast.makeText(getApplicationContext(), "wifi is disabled.. making it enabled", Toast.LENGTH_LONG).show();
mWifiManager.setWifiEnabled(true);
}
mWifiListener = new WifiListener();
adapter = new WifiAdapter(WifiListActivity.this, mScanResults);
mListWifi.setAdapter(adapter);
mListWifi.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
connectToWifi(i);
}
});
}
#Override
public void onClick(View view) {
mWifiManager.startScan();
Toast.makeText(this, "Scanning....", Toast.LENGTH_SHORT).show();
}
#Override
protected void onResume() {
super.onResume();
try {
registerReceiver(mWifiListener, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
mWifiManager.startScan();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onPause() {
super.onPause();
try {
unregisterReceiver(mWifiListener);
} catch (Exception e) {
e.printStackTrace();
}
}
private void connectToWifi(int position) {
final ScanResult item = mScanResults.get(position);
String Capabilities = item.capabilities;
if (Capabilities.contains("WPA")) {
AlertDialog.Builder builder = new AlertDialog.Builder(WifiListActivity.this);
builder.setTitle("Password:");
final EditText input = new EditText(WifiListActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
builder.setView(input);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String m_Text = input.getText().toString();
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + item.SSID + "\"";
wifiConfiguration.preSharedKey = "\"" + m_Text + "\"";
wifiConfiguration.hiddenSSID = true;
wifiConfiguration.status = WifiConfiguration.Status.ENABLED;
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
wifiConfiguration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
wifiConfiguration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
int res = mWifiManager.addNetwork(wifiConfiguration);
boolean b = mWifiManager.enableNetwork(res, true);
finishActivity(wifiConfiguration, res);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
} else if (Capabilities.contains("WEP")) {
AlertDialog.Builder builder = new AlertDialog.Builder(WifiListActivity.this);
builder.setTitle("Title");
final EditText input = new EditText(WifiListActivity.this);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
builder.setView(input);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String m_Text = input.getText().toString();
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + item.SSID + "\"";
wifiConfiguration.wepKeys[0] = "\"" + m_Text + "\"";
wifiConfiguration.wepTxKeyIndex = 0;
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
wifiConfiguration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
int res = mWifiManager.addNetwork(wifiConfiguration);
Log.d("WifiPreference", "add Network returned " + res);
boolean b = mWifiManager.enableNetwork(res, true);
Log.d("WifiPreference", "enableNetwork returned " + b);
finishActivity(wifiConfiguration, res);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
builder.show();
} else {
WifiConfiguration wifiConfiguration = new WifiConfiguration();
wifiConfiguration.SSID = "\"" + item.SSID + "\"";
wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
int res = mWifiManager.addNetwork(wifiConfiguration);
Log.d("WifiPreference", "add Network returned " + res);
boolean b = mWifiManager.enableNetwork(res, true);
Log.d("WifiPreference", "enableNetwork returned " + b);
finishActivity(wifiConfiguration, res);
}
}
private void finishActivity(WifiConfiguration mWifiConfiguration, int networkId) {
mWifiConfiguration.networkId = networkId;
Util.savePrinterConfiguration(WifiListActivity.this, mWifiConfiguration);
Intent intent = new Intent();
setResult(Constants.RESULT_CODE_PRINTER, intent);
finish();
}
public class WifiListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
mScanResults = mWifiManager.getScanResults();
Log.e("scan result size ", "" + mScanResults.size());
adapter.setElements(mScanResults);
}
}
}
WifiAdapter.java
public class WifiAdapter extends BaseAdapter {
private Activity mActivity;
private List<ScanResult> mWifiList = new ArrayList<ScanResult>();
public WifiAdapter(Activity mActivity, List<ScanResult> mWifiList) {
this.mActivity = mActivity;
this.mWifiList = mWifiList;
}
#Override
public int getCount() {
return mWifiList.size();
}
#Override
public Object getItem(int i) {
return mWifiList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.custom_wifi_list_item, null);
TextView txtWifiName = (TextView) view.findViewById(R.id.txtWifiName);
txtWifiName.setText(mWifiList.get(i).SSID);
return view;
}
public void setElements(List<ScanResult> mWifis) {
this.mWifiList = mWifis;
notifyDataSetChanged();
}
}
PrintCompleteService.java
public interface PrintCompleteService {
public void onMessage(int status);
}
PrintServiceAdapter.java
public class PrintServicesAdapter extends PrintDocumentAdapter {
private Activity mActivity;
private int pageHeight;
private int pageWidth;
private PdfDocument myPdfDocument;
private int totalpages = 1;
private File pdfFile;
private PrintCompleteService mPrintCompleteService;
public PrintServicesAdapter(Activity mActivity, File pdfFile) {
this.mActivity = mActivity;
this.pdfFile = pdfFile;
this.totalpages = Util.computePDFPageCount(pdfFile);
this.mPrintCompleteService = (PrintCompleteService) mActivity;
}
#Override
public void onLayout(PrintAttributes oldAttributes,
PrintAttributes newAttributes,
CancellationSignal cancellationSignal,
LayoutResultCallback callback,
Bundle metadata) {
myPdfDocument = new PrintedPdfDocument(mActivity, newAttributes);
pageHeight =
newAttributes.getMediaSize().getHeightMils() / 1000 * 72;
pageWidth =
newAttributes.getMediaSize().getWidthMils() / 1000 * 72;
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
if (totalpages > 0) {
PrintDocumentInfo.Builder builder = new PrintDocumentInfo
.Builder(pdfFile.getName())
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(totalpages);
PrintDocumentInfo info = builder.build();
callback.onLayoutFinished(info, true);
} else {
callback.onLayoutFailed("Page count is zero.");
}
}
#Override
public void onWrite(final PageRange[] pageRanges,
final ParcelFileDescriptor destination,
final CancellationSignal cancellationSignal,
final WriteResultCallback callback) {
InputStream input = null;
OutputStream output = null;
try {
input = new FileInputStream(pdfFile);
output = new FileOutputStream(destination.getFileDescriptor());
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buf)) > 0) {
output.write(buf, 0, bytesRead);
}
callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
} catch (FileNotFoundException ee) {
//Catch exception
} catch (Exception e) {
//Catch exception
} finally {
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
cancellationSignal.setOnCancelListener(new CancellationSignal.OnCancelListener() {
#Override
public void onCancel() {
mPrintCompleteService.onMessage(Constants.PRINTER_STATUS_CANCELLED);
}
});
}
#Override
public void onFinish() {
mPrintCompleteService.onMessage(Constants.PRINTER_STATUS_COMPLETED);
}
}
Util.java
public class Util {
public static String connectionInfo(Activity mActivity) {
String result = "not connected";
ConnectivityManager cm = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase(Constants.CONTROLLER_WIFI)) {
if (ni.isConnected()) {
result = Constants.CONTROLLER_WIFI;
break;
}
} else if (ni.getTypeName().equalsIgnoreCase(Constants.CONTROLLER_MOBILE)) {
if (ni.isConnected()) {
result = Constants.CONTROLLER_MOBILE;
break;
}
}
}
return result;
}
public static void saveWifiConfiguration(Activity mActivity, WifiConfiguration mWifiConfiguration) {
Gson mGson = new Gson();
Type mType = new TypeToken<WifiConfiguration>() {
}.getType();
String sJson = mGson.toJson(mWifiConfiguration, mType);
SharedPreferences mSharedPrefs = mActivity.getSharedPreferences(Constants.DEMO_PREFERENCES, Context.MODE_PRIVATE);
mSharedPrefs.edit().putString(Constants.CONTROLLER_WIFI_CONFIGURATION, sJson).commit();
}
public static void savePrinterConfiguration(Activity mActivity, WifiConfiguration mPrinterConfiguration) {
Gson mGson = new Gson();
Type mType = new TypeToken<WifiConfiguration>() {
}.getType();
String sJson = mGson.toJson(mPrinterConfiguration, mType);
SharedPreferences mSharedPrefs = mActivity.getSharedPreferences(Constants.DEMO_PREFERENCES, Context.MODE_PRIVATE);
mSharedPrefs.edit().putString(Constants.CONTROLLER_PRINTER_CONFIGURATION, sJson).commit();
}
public static WifiConfiguration getWifiConfiguration(Activity mActivity, String configurationType) {
WifiConfiguration mWifiConfiguration = new WifiConfiguration();
Gson mGson = new Gson();
SharedPreferences mSharedPrefs = mActivity.getSharedPreferences(Constants.DEMO_PREFERENCES, Context.MODE_PRIVATE);
Type mWifiConfigurationType = new TypeToken<WifiConfiguration>() {
}.getType();
String mWifiJson = "";
if (configurationType.equalsIgnoreCase(Constants.CONTROLLER_WIFI)) {
mWifiJson = mSharedPrefs.getString(Constants.CONTROLLER_WIFI_CONFIGURATION, "");
} else if (configurationType.equalsIgnoreCase(Constants.CONTROLLER_PRINTER)) {
mWifiJson = mSharedPrefs.getString(Constants.CONTROLLER_PRINTER_CONFIGURATION, "");
}
if (!mWifiJson.isEmpty()) {
mWifiConfiguration = mGson.fromJson(mWifiJson, mWifiConfigurationType);
} else {
mWifiConfiguration = null;
}
return mWifiConfiguration;
}
public static void storeCurrentWiFiConfiguration(Activity mActivity) {
try {
WifiManager wifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.getSSID())) {
WifiConfiguration mWifiConfiguration = new WifiConfiguration();
mWifiConfiguration.networkId = connectionInfo.getNetworkId();
mWifiConfiguration.BSSID = connectionInfo.getBSSID();
mWifiConfiguration.hiddenSSID = connectionInfo.getHiddenSSID();
mWifiConfiguration.SSID = connectionInfo.getSSID();
// store it for future use -> after print is complete you need to reconnect wifi to this network.
saveWifiConfiguration(mActivity, mWifiConfiguration);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static int computePDFPageCount(File file) {
RandomAccessFile raf = null;
int pages = 0;
try {
raf = new RandomAccessFile(file, "r");
RandomAccessFileOrArray pdfFile = new RandomAccessFileOrArray(
new RandomAccessSourceFactory().createSource(raf));
PdfReader reader = new PdfReader(pdfFile, new byte[0]);
pages = reader.getNumberOfPages();
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return pages;
}
}