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);
}
Related
I have this service which send my location to server and get some data from it.
package com.speed00.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.widget.Toast;
import com.google.gson.Gson;
import com.speed00.R;
import com.speed00.constant.AppConstant;
import com.speed00.helper.FunctionHelper;
import com.speed00.model.achivment.StepHelper;
import com.speed00.model.ride.RideResultResponse;
import com.speed00.model.ride.UpdateLocationData;
import com.speed00.model.ride.UpdateLocationResponse;
import com.speed00.prefrences.MyPreferences;
import com.speed00.prefrences.MySharedPreference;
import com.speed00.retrofit.ApiUtils;
import com.speed00.stepdetucter.StepDetector;
import com.speed00.stepdetucter.StepListener;
import com.speed00.ui.activity.HomeActivity;
import com.speed00.utils.Logger;
import com.speed00.utils.MySensorEventListener;
import com.speed00.utils.NetworkConnection;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MyService extends Service implements StepListener, SensorEventListener {
// constant
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
private Double locationRange = 1.0;
private String oldDegree;
private boolean isServiceRunning;
private int numSteps = 0;
private final int FINAL_STEP = 15;
private SensorManager sensorManager;
private Sensor accel;
String speed_received = "0";
private boolean pedoMetterHasStarted = false;
String pLatitude;
String pLongitude;
private SensorEventListener eListener;
private Sensor accelerometer, magFieldSensor;
private StepDetector simpleStepDetector;
#Override
public IBinder onBind(Intent intent) {
return null;
}
private BroadcastReceiver message = new BroadcastReceiver() {
#Override
public void onReceive(Context context, final Intent intent) {
// TODO Auto-generated method stub
new Handler().post(new Runnable() {
#Override
public void run() {
speed_received = intent.getStringExtra("current speed");
Logger.e("speed__recv" + speed_received);
if (speed_received != null) {
// setSpeedValue(speed_received);//this method is calling to set speed.
//This method is calling to validate Timer For Ride
if (speed_received.equalsIgnoreCase("0")) {
if (!pedoMetterHasStarted) {
numSteps = 0;
statPedoMeter();
}
}
//Calculating distance value
String latitude = MySharedPreference.getInstance(MyService.this).getLatitude();
String longitude = MySharedPreference.getInstance(MyService.this).getLongitude();
if (TextUtils.isEmpty(pLatitude)) {
pLatitude = latitude;
pLongitude = longitude;
} else {
/*
* if distance is more then 2 km then its calculatiog.
*
* */
Location pLocation = new Location("P");
pLocation.setLongitude(Double.parseDouble(pLatitude));
pLocation.setLongitude(Double.parseDouble(pLongitude));
Location nLocation = new Location("N");
nLocation.setLongitude(Double.parseDouble(latitude));
nLocation.setLongitude(Double.parseDouble(longitude));
Logger.e("distance----" + pLocation.distanceTo(nLocation));
if (pLocation.distanceTo(nLocation) >= 10) {
pLatitude = latitude;
pLongitude = longitude;
}
}
}
}
});
}
};
#Override
public void onCreate() {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
eListener = new MySensorEventListener(this, sensorManager);//for direction
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//callback sensor of ui
sensorManager.registerListener(eListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(eListener, magFieldSensor, SensorManager.SENSOR_DELAY_NORMAL);
assert sensorManager != null;
accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
simpleStepDetector = new StepDetector();
simpleStepDetector.registerListener(this);
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
isServiceRunning = true;
// Toast.makeText(getApplicationContext(), "service started", Toast.LENGTH_SHORT).show();
// cancel if already existed
if (mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
// new Timer().scheduleAtFixedRate(new TimeDisplayTimerTask(), 100, NOTIFY_INTERVAL);
runLoop();
LocalBroadcastManager.getInstance(this).registerReceiver(message,
new IntentFilter("send"));
}
private void runLoop() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
updateDriverLocation();
if (isServiceRunning)
runLoop();
}
}, 1000);
}
/*
*
* This method is calling to update driver location
* */
private void updateDriverLocation() {
//Get all user details data.
String userId = MySharedPreference.getInstance(getApplicationContext()).getDriverId();
String latitudeData = MySharedPreference.getInstance(getApplicationContext()).getLatitude();
String longitudeData = MySharedPreference.getInstance(getApplicationContext()).getLongitude();
String speedData = MySharedPreference.getInstance(getApplicationContext()).getSpeedData();//how to roinf
Logger.e("SERVER " + latitudeData + " " + longitudeData);
Logger.e("SPEED " + speedData);
String directionValue = MySharedPreference.getInstance(getApplicationContext()).getDirectionValue();
String speeding = MySharedPreference.getInstance(getApplicationContext()).getSpeeding();
String language = MyPreferences.newInstance(getApplicationContext()).getLanguage();//send speeding data to bakend.
String directionText = MySharedPreference.getInstance(getApplicationContext()).getDirectionText();
long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(getApplicationContext()).getStartTime());
String validateUTurn = validateUTurn();
// Logger.e("update_request--" + request);
ApiUtils.getAPIService().updateDriverLocation(validateUTurn, directionText, speeding, "" + driveTime, language, userId,
AppConstant.START_RIDE, speedData, directionValue, latitudeData, longitudeData).enqueue(new Callback<UpdateLocationResponse>() {
#Override
public void onResponse(Call<UpdateLocationResponse> call, Response<UpdateLocationResponse> response) {
if (response.isSuccessful()) {
UpdateLocationResponse updateLocationResponse = response.body();
if (updateLocationResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
if (updateLocationResponse.getData().size() > 0) {
UpdateLocationData updateLocationData = updateLocationResponse.getData().get(0);
String eventData = FunctionHelper.validateData(updateLocationData);
broadCastEventData(eventData, updateLocationResponse.getErrorCode());
broadCastResponseData(updateLocationResponse);
}
}
}
}
#Override
public void onFailure(Call<UpdateLocationResponse> call, Throwable t) {
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
/*
*
*This method is calling to validateUTurn.
*
*
* */
private String validateUTurn() {
String currentDegree = MySharedPreference.getInstance(this).getDirectionValue();
String uTurnStatus = "0";
if (TextUtils.isEmpty(oldDegree)) {
oldDegree = currentDegree;
uTurnStatus = "0";
return uTurnStatus;
} else {
if (oldDegree == "0.0") {
oldDegree = currentDegree;
}
if (Float.parseFloat(oldDegree) <= Float.parseFloat(currentDegree)) {
uTurnStatus = "1";
} else {
uTurnStatus = "0";
}
if (Float.parseFloat(oldDegree) == 360 || Float.parseFloat(oldDegree) > 270) {
if (Float.parseFloat(currentDegree) > 0 && Float.parseFloat(oldDegree) <= 90) {
uTurnStatus = "1";
}
}
oldDegree = currentDegree;
return uTurnStatus;
}
}
public synchronized void broadCastEventData(String eventData, String errorCode) {
Intent intent = new Intent("event_broad_cast");
intent.putExtra("data", eventData);
intent.putExtra("error", errorCode);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
/*
* This method is calling to broadcast event data
* */
/*
* This method is calling to broadcast event data
* */
public synchronized void broadCastResponseData(UpdateLocationResponse updateLocationData) {
Intent intent = new Intent("location_update");
Bundle args = new Bundle();
args.putSerializable("data", (Serializable) updateLocationData);
intent.putExtra("myvalue", args);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
isServiceRunning = false;
LocalBroadcastManager.getInstance(this).unregisterReceiver(message);
// stopPedoMeter();
}
#Override
public void step(long timeNs) {
if (numSteps < 16)
Toast.makeText(this, "" + numSteps, Toast.LENGTH_SHORT).show();
saveStep();
if (calculateSteps()) {
stopRideAfter25step();
stopPedoMeter();//this method is calling to stop ResultActivity
} else if (Double.parseDouble(MySharedPreference.getInstance(this).getSpeedData()) > 10) {
MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
numSteps = 0;
} else {
Logger.e("stepsss " + numSteps);
numSteps = numSteps + 1;
}
}
private void stopRideAfter25step() {
MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
String speed = MySharedPreference.getInstance(this).getSpeedData();
String direction = MySharedPreference.getInstance(this).getDirectionValue();
String latitude = MySharedPreference.getInstance(this).getLatitude();
String longitude = MySharedPreference.getInstance(this).getLongitude();
String driverId = MySharedPreference.getInstance(this).getDriverId();
String language = MyPreferences.newInstance(this).getLanguage();
String speeding = MySharedPreference.getInstance(this).getSpeeding();
long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(this).getStartTime());
//validate internet connection
if (NetworkConnection.isConnection(this)) {
stopRide("" + driveTime, language, speeding, driverId, latitude, longitude, AppConstant.STOP_RIDE, speed, direction);
} else {
Toast.makeText(this, getString(R.string.valid_please_check_network_connection), Toast.LENGTH_LONG).show();
}
}
public void stopRide(final String driveTime, final String languageKey, final String speedLimit, final String driverId, final String latitude, final String longitude, String rideStatus, final String speed, final String direction) {
String[] param = {driveTime, languageKey, speedLimit, driverId, speed, direction, latitude, longitude};
new stopLoc(this).execute(param);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
simpleStepDetector.updateAccel(event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private static class stopLoc extends AsyncTask<String[], Void, Void> {
Context mContext;
public stopLoc(Context mContext) {
this.mContext = mContext;
}
#Override
protected Void doInBackground(String[]... strings) {
Logger.e("stepsss stopingggg");
String driveTime = strings[0][0];
String languageKey = strings[0][1];
String speedLimit = strings[0][2];
String driverId = strings[0][3];
String speed = strings[0][4];
String direction = strings[0][5];
String latitude = strings[0][6];
String longitude = strings[0][7];
ApiUtils.getAPIService().stopTrip(driveTime, languageKey, speedLimit, driverId, AppConstant.STOP_RIDE, speed, direction, latitude, longitude).enqueue(new Callback<RideResultResponse>() {
#Override
public void onResponse(Call<RideResultResponse> call, Response<RideResultResponse> response) {
Logger.e("response----" + new Gson().toJson(response.body()));
if (response.isSuccessful()) {
String errorCode = response.body().getErrorCode();
if (errorCode.equalsIgnoreCase(AppConstant.ERROR_CODE)) {
tripSuccessData(response.body(), mContext);
} else {
Toast.makeText(mContext, "" + mContext.getString(R.string.text_some_erroroccurs), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<RideResultResponse> call, Throwable t) {
Toast.makeText(mContext, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return null;
}
}
public static void tripSuccessData(Object data, Context context) {
RideResultResponse resultResponse = (RideResultResponse) data;
if (resultResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
FunctionHelper.enableUserIntraction();
HomeActivity.bSpeedStatus = false;
Intent intent = new Intent("trip_ended");
intent.putExtra("trip_info", resultResponse.getData().get(0));
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
((MyService) context).stopSelf();
} else {
Toast.makeText(context, resultResponse.getErrorMsg(), Toast.LENGTH_SHORT).show();
}
}
private boolean calculateSteps() {
ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
ArrayList<StepHelper> newList = new ArrayList<>();
for (int i = 0; i < arrayList.size(); i++) {
long seconds = FunctionHelper.getDifference(arrayList.get(i).getTime());
if ((int) seconds < 180) {
newList.add(arrayList.get(i));
}
}
if (numSteps - newList.get(0).getSteps() >= FINAL_STEP) {
return true;
} else {
MySharedPreference.getInstance(this).setSteps(newList);
return false;
}
}
private void saveStep() {
ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
if (arrayList == null) {
arrayList = new ArrayList<>();
}
arrayList.add(new StepHelper(FunctionHelper.getCurrentDateWitTime(), numSteps));
MySharedPreference.getInstance(this).setSteps(arrayList);
}
private void statPedoMeter() {
// Toast.makeText(this, "start count", Toast.LENGTH_SHORT).show();
pedoMetterHasStarted = true;
MySharedPreference.getInstance(this).setStartPedoMeterTime(FunctionHelper.getCurrentDateWitTime());//store current time
if (sensorManager != null)
sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
}
/*
* This method is calling to stop pedo meter
*
* */
private void stopPedoMeter() {
numSteps = 0;
pedoMetterHasStarted = false;
sensorManager.unregisterListener(this, accelerometer);
sensorManager.unregisterListener(this, accel);
sensorManager.unregisterListener(this, magFieldSensor);
sensorManager = null;
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
Logger.e("MyService --- " + "isRuning");
if (HomeActivity.bSpeedStatus) {
updateDriverLocation();
}
}
});
}
}
}
My app starts and use only 170 MB , but after starting this service , it becomes 220 MB and after finishing it, it still 220 and if i open it again , ram become 240 and if i finish it still 240 and if i open it again it become 260 and so on until app crash
what's the wrong in the service ?
i make sure that it's stopped but don't know why ram not reduced after this service is finished
Try this approache, don't put the stopSelf() inside a static method. Instead, you should call startService again and add an action to the Intent.
So this is how an example actionable service should look like:
public class ExampleService
extends Service {
public static final String START_SERVICE_ACTION = "com.example.action.START_SERVICE";
public static final String STOP_SERVICE_ACTION = "com.example.action.STOP_SERVICE";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String intentAction = intent.getAction();
switch (intentAction) {
case START_SERVICE_ACTION:
//
break;
case STOP_SERVICE_ACTION:
stopSelf();
break;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
// Used only in case if services are bound (Bound Services).
return null;
}
}
Interact with the Service from somewhere:
Start with it like this:
Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.START_SERVICE_ACTION);
startService(service);
Stop it like this:
Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.STOP_SERVICE_ACTION);
startService(service);
You don't really need to pass the START_SERVICE_ACTION in this example, just added it to better understand the design.
I am new to Android App developing and BLE, and I am learning these using the sample code BluetoothLeGatt [The one I imported from Android Studio].
What I Can Do Now:
I can scan all available ble devices. Once I click on my ble device, I will be directed to a new page, and I will see a list of services available. If I click on a specific service, I can see its characteristics. If I click on the characteristic, I can see the obtained data.
What I want
I was wondering is there a way that I can programmatically/automatically select a service and a characteristic to get data? What I want is that once I click my ble device, I will be able to see the data.
Does anyone know how to modify the code? The following code is the DeviceControlActivity.
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.bluetoothlegatt;
import android.app.Activity;
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.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* 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
{
private final static String TAG = DeviceControlActivity.class.getSimpleName();
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 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 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);
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));
}
}
};
// 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() {
#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.
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
return true;
}
return false;
}
};
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);
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);
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(TAG, "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;
}
#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);
}
}
// 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);
}
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;
}
}
First You need to store all service in one array then get all characteristics of that service and store in another array.
Then use this characteristics array for read and write .
I'm attempting to receive data from my Texas sensor tag, but so far I just managed to connect and write characteristics to it.
this is my setCharacteristicNotification();
the part commented below does not work and I didn't managed to use it.
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if(bluetoothAdapter == null || bluetoothGatt == null) return;
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if(GattUUIDs.containsUuid(characteristic.getUuid())) {
// BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
// UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(
GattUUIDs.UUID_CLIENT_CHAR_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE |
BluetoothGattDescriptor.PERMISSION_READ);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
}
}
When I try to call the commented block, this is what I receive:
java.lang.NullPointerException: Attempt to invoke virtual method
'boolean android.bluetooth.BluetoothGattDescriptor.setValue(byte[])'
on a null object reference
This is my Client Characteristic Configuration UUID:
public static final UUID UUID_CLIENT_CHAR_CONFIG =
UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG);
public static String CLIENT_CHARACTERISTIC_CONFIG = "f0002902-0451-4000-b000-000000000000";
I think that it has some sort of problem in my descriptor because I can register it but I never got a callback from it.
If it helps, this is my Service:
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import java.util.List;
import java.util.UUID;
/**
* Created by alan on 2/23/16.
*/
public class DeviceService extends Service {
private final static String TAG = DeviceService.class.getSimpleName();
private BluetoothGatt bluetoothGatt;
private String deviceAddress;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private int connectionState = STATE_DISCONNECTED;
public final IBinder binder = new LocalBinder();
public static final int STATE_DISCONNECTED = 0;
public static final int STATE_CONNECTING = 1;
public static final int STATE_CONNECTED = 2;
public static final String ACTION_GATT_SERVICES_DISCOVERED = "action_gatt_services_discovered";
public static final String ACTION_GATT_DISCONNECTED = "action_gatt_disconnected";
public static final String ACTION_GATT_CONNECTED = "action_gatt_connected";
public static final String ACTION_DATA_AVAILABLE = "action_data_available";
public static final String ACTION_DATA_NOTIFY = "action_data_notify";
public static final String ACTION_DATA_WRITE = "action_data_write";
public static final String ACTION_DATA_READ = "action_data_read";
public static final String EXTRA_DATA = "extra_data";
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
public boolean initialize() {
if(bluetoothManager == null) {
bluetoothManager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
if(bluetoothManager == null) {
Log.e(TAG,"CANNOT INITIALIZE BLUETOOTH");
return false;
}
}bluetoothAdapter = bluetoothManager.getAdapter();
if(bluetoothAdapter == null) {
Log.e(TAG,"CANNOT FIND AN ADAPTER");
return false;
}return true;
}
public boolean connect(final String address) {
Log.w(TAG,"CONNECT PROCESS INITIALIZED");
if(bluetoothAdapter == null || address == null) {
Log.e(TAG,"ADAPTER NOT INITIALIZED");
return false;
}
//previously connected device, attempt to reconnect
if(deviceAddress != null && deviceAddress.equals(address)
&&bluetoothGatt != null) {
Log.d(TAG, "TRYING TO USE EXISTING GATT");
if(bluetoothGatt.connect()) {
connectionState = STATE_CONNECTING;
bluetoothGatt.connect();
return true;
} else
return false;
}
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if(device == null) {
Log.e(TAG, "DEVICE NOT FOUND");
return false;
}
bluetoothGatt = device.connectGatt(this, false, gattCallback);
deviceAddress = address;
connectionState = STATE_CONNECTING;
return true;
}
public void disconnect() {
if(bluetoothAdapter == null || bluetoothGatt == null) {
Log.w(TAG, "BLUETOOTH NOT INITIALIZED");
return;
}
bluetoothGatt.disconnect();
}
public void close() {
if(bluetoothGatt == null)
return;
bluetoothGatt.close();
bluetoothGatt = null;
}
public class LocalBinder extends Binder {
DeviceService getService() {
return DeviceService.this;
}
}
private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if(newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
connectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG,"CONNECTED TO GATT SERVER!");
bluetoothGatt.discoverServices();
} else if(newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
connectionState = STATE_DISCONNECTED;
Log.i(TAG,"DISCONNECTED FROM GATT SERVER");
broadcastUpdate(intentAction);
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.e(TAG,"STATUS: " + String.valueOf(status));
if (status == BluetoothGatt.GATT_SUCCESS)
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS)
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.e(TAG,"CHAR CHANGED \n" + gatt.toString() + "\n" + characteristic.getUuid().toString() + "\n");
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.e(TAG,"CHAR WROTE" + gatt.toString() + "\n" + characteristic.getUuid().toString() + "\n");
if(status == BluetoothGatt.GATT_SUCCESS)
broadcastUpdate(ACTION_DATA_WRITE, characteristic);
}
};
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if(bluetoothAdapter == null || bluetoothGatt == null) {
Log.e(TAG, "ADAPTER NOT INITIALIZED");
return;
}
bluetoothGatt.readCharacteristic(characteristic);
}
public void writeCharacteristic(BluetoothGattCharacteristic characteristic, byte[] value) {
if(bluetoothAdapter == null || bluetoothGatt == null) {
Log.e(TAG, "ADAPTER NOT INITIALIZED");
return;
}
characteristic.setValue(value);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
bluetoothGatt.writeCharacteristic(characteristic);
System.out.println("Write value: " + value[0] + " on UUID: " + characteristic.getUuid().toString());
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if(bluetoothAdapter == null || bluetoothGatt == null) return;
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if(GattUUIDs.containsUuid(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
// BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(
// GattUUIDs.UUID_CLIENT_CHAR_CONFIG, BluetoothGattDescriptor.PERMISSION_WRITE |
// BluetoothGattDescriptor.PERMISSION_READ);
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
}
}
public void setCharacteristicIndication(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if(bluetoothAdapter ==null || bluetoothGatt == null) return;
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
bluetoothGatt.writeDescriptor(descriptor);
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
final UUID uuid = characteristic.getUuid();
Log.w(TAG,"BROADCAST UPDATE WITH ACTION: " + action);
if(GattUUIDs.containsUuid(uuid)) {
Log.e(TAG,"PASSOU AQUI");
int flag = characteristic.getProperties();
int format;
if((flag & 0x01) != 0)
format = BluetoothGattCharacteristic.FORMAT_UINT16;
else
format = BluetoothGattCharacteristic.FORMAT_UINT8;
byte[] data = characteristic.getValue();
if (GattUUIDs.UUID_IR_TEMPERATURE_MEASUREMENT.equals(uuid)) {
float objectTemperature = ((((float)data[1] * 256 + (float)data[0]) / (float)4)) * (float)0.03125;
float ambientTemperature = ((((float)data[3] * 256 + (float)data[2]) / (float)4)) * (float)0.03125;
// final int temp_data = characteristic.getIntValue(format, 1);
intent.putExtra(EXTRA_DATA, String.format("%.2f %.2f", objectTemperature, ambientTemperature));
} else if (GattUUIDs.UUID_IR_TEMPERATURE_CONFIG.equals(uuid)) {
if (data[0] == 0)
intent.putExtra(EXTRA_DATA, "IR DISABLED");
else
intent.putExtra(EXTRA_DATA, "IR ENABLED");
} else if (GattUUIDs.UUID_IR_TEMPERATURE_PERIOD.equals(uuid))
intent.putExtra(EXTRA_DATA, String.format("%d",data[0]*10));
else if (GattUUIDs.UUID_OPTICAL_MEASUREMENT.equals(uuid)) {
int m = (data[1] * 256 + data[0]) & 0x0FFF;
int e = ((data[1] * 256 + data[0]) & 0xF000) >> 12;
double lux = m * 0.01 * Math.pow(2.0,e);
intent.putExtra(EXTRA_DATA, String.format("%.2f",lux));
} else if (GattUUIDs.UUID_OPTICAL_CONFIG.equals(uuid)) {
if(data[0] == 0)
intent.putExtra(EXTRA_DATA, "OPTICAL DISABLED");
else
intent.putExtra(EXTRA_DATA, "OPTICAL ENABLED");
} else if (GattUUIDs.UUID_OPTICAL_PERIOD.equals(uuid))
intent.putExtra(EXTRA_DATA, String.format("%d",data[0] * 10));
else if (GattUUIDs.UUID_MOVEMENT_MEASUREMENT.equals(uuid))
intent.putExtra(EXTRA_DATA, String.format("%d %d %d %d %d %d %d %d %d",
(data[0] + data[1]*256),
(data[2] + data[3]*256),
(data[4] + data[5]*256),
(data[6] + data[7]*256),
(data[8] + data[9]*256),
(data[10] + data[11]*256),
(data[12] + data[13]*256),
(data[14] + data[15]*256),
(data[16] + data[17]*256)));
else if (GattUUIDs.UUID_MOVEMENT_CONFIG.equals(uuid)) {
if (data[0] == 0)
intent.putExtra(EXTRA_DATA, "MOVEMENT DISABLED");
else
intent.putExtra(EXTRA_DATA, "MOVEMENT ENABLEd");
} else if (GattUUIDs.UUID_MOVEMENT_PERIOD.equals(uuid))
intent.putExtra(EXTRA_DATA, String.format("%d",data[0] * 10));
else {
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ",byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
}
}
}
sendBroadcast(intent);
}
public List<BluetoothGattService> getSupportedGattServices() {
if(bluetoothGatt == null) return null;
return bluetoothGatt.getServices();
}
}
and this is my device control:
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.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
/**
* Created by alan on 2/23/16.
*/
public class DeviceControl extends AppCompatActivity {
private final String TAG = DeviceControl.class.getSimpleName();
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacterics = new ArrayList<>();
private BluetoothGattCharacteristic bluetoothGattCharacteristic;
public static String ADDRESS;
private DeviceService deviceService;
private boolean connected = false;
private TextView dataText;
private Switch temperatureSwitch,
movementSwitch,
opticalSwitch;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
private final ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e(TAG,"ONSERVICECONNECTED");
deviceService = ((DeviceService.LocalBinder)service).getService();
if(!deviceService.initialize())
finish();
deviceService.connect(ADDRESS);
}
#Override
public void onServiceDisconnected(ComponentName name) {
deviceService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceBundle) {
super.onCreate(savedInstanceBundle);
setContentView(R.layout.activity_device_control);
dataText = (TextView)findViewById(R.id.dataText);
temperatureSwitch = (Switch)findViewById(R.id.temperatureSwitch);
movementSwitch = (Switch)findViewById(R.id.movementSwitch);
opticalSwitch = (Switch)findViewById(R.id.opticalSwitch);
temperatureSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked && connected)
writeCharacteristic(GattUUIDs.UUID_IR_TEMPERATURE_CONFIG, true);
else if(!isChecked && connected)
writeCharacteristic(GattUUIDs.UUID_IR_TEMPERATURE_CONFIG, false);
}
});
Bundle extras = getIntent().getExtras();
if(extras != null) {
setTitle(extras.getString("title"));
ADDRESS = extras.getString("address");
Intent intent = new Intent(this, DeviceService.class);
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
registerReceiver(broadcastReceiver, makeIntentFilter());
}
public void writeCharacteristic(UUID toFind, boolean read) {
BluetoothGattCharacteristic gattCharacteristic = null;
byte[] enable = {(byte)0x01},
disable = {(byte)0x00};
for(int i = 0; i < mGattCharacterics.size(); i++) {
for(int j = 0; j < mGattCharacterics.get(i).size(); j++) {
if(mGattCharacterics.get(i).get(j).getUuid().equals(toFind))
gattCharacteristic = mGattCharacterics.get(i).get(j);
}
}
if(gattCharacteristic != null) {
if(read)
deviceService.writeCharacteristic(gattCharacteristic, enable);
else
deviceService.writeCharacteristic(gattCharacteristic, disable);
deviceService.setCharacteristicNotification(gattCharacteristic, true);
} else
Log.e(TAG,"NOTHING FOUND");
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(broadcastReceiver, makeIntentFilter());
Log.w(TAG,"REGISTER RECEIVER");
if (deviceService != null) {
final boolean result = deviceService.connect(ADDRESS);
Log.d(TAG,"CONNECT RESULT = " + result);
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
#Override
public void onBackPressed() {
super.onBackPressed();
deviceService.disconnect();
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
deviceService = null;
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.e(TAG,"BROADCAST ACTION"+action);
switch (action) {
case DeviceService.ACTION_GATT_CONNECTED:
connected = true;
break;
case DeviceService.ACTION_GATT_DISCONNECTED:
connected = false;
break;
case DeviceService.ACTION_GATT_SERVICES_DISCOVERED:
getGattServices(deviceService.getSupportedGattServices());
break;
case DeviceService.ACTION_DATA_AVAILABLE:
displayData(intent.getStringExtra(DeviceService.EXTRA_DATA));
}
}
};
private void displayData(String data) {
if(data != null)
dataText.setText(data);
}
private void getGattServices(List<BluetoothGattService> gattServices) {
if(gattServices == null) return;
String uuid = null;
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<>();
mGattCharacterics = new ArrayList<>();
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<>();
uuid = gattService.getUuid().toString();
currentServiceData.put(LIST_NAME, GattAttributes.lookup(uuid, "UnknownService"));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<>();
List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<>();
for(BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(LIST_NAME, GattAttributes.lookup(uuid, "UnknownCharacteristic"));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
//System.out.println("GATTCHAR\n\n" + gattCharacteristic.toString()+"\n");
}
mGattCharacterics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
}
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(DeviceService.ACTION_GATT_CONNECTED);
intentFilter.addAction(DeviceService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(DeviceService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(DeviceService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
Thanks for your attention.
I designed a chat application but if I write text and click on send the application is force closed. I send username, ip and port information to the other activity.
messaging code :
import java.io.UnsupportedEncodingException;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.android.chat.IAppManager;
import com.android.chat.IMService;
import com.android.chat.FriendController;
import com.android.chat.LocalStorageHandler;
import com.android.chat.FriendInfo;
import com.android.chat.MessageInfo;
import com.android.chats.R;
public class Messaging extends Activity {
private static final int MESSAGE_CANNOT_BE_SENT = 0;
public String username;
private EditText messageText;
private EditText messageHistoryText;
private Button sendMessageButton;
private IAppManager imService;
private FriendInfo friend = new FriendInfo();
private LocalStorageHandler localstoragehandler;
private Cursor dbCursor;
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((IMService.IMBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(Messaging.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.messaging_screen); //messaging_screen);
messageHistoryText = (EditText) findViewById(R.id.messageHistory);
messageText = (EditText) findViewById(R.id.message);
messageText.requestFocus();
sendMessageButton = (Button) findViewById(R.id.sendMessageButton);
Bundle extras = this.getIntent().getExtras();
friend.userName = extras.getString(FriendInfo.USERNAME);
friend.ip = extras.getString(FriendInfo.IP);
friend.port = extras.getString(FriendInfo.PORT);
String msg = extras.getString(MessageInfo.MESSAGETEXT);
setTitle("Messaging with " + friend.userName);
// EditText friendUserName = (EditText) findViewById(R.id.friendUserName);
// friendUserName.setText(friend.userName);
localstoragehandler = new LocalStorageHandler(this);
dbCursor = localstoragehandler.get(friend.userName, IMService.USERNAME );
if (dbCursor.getCount() > 0){
int noOfScorer = 0;
dbCursor.moveToFirst();
while ((!dbCursor.isAfterLast())&&noOfScorer<dbCursor.getCount())
{
noOfScorer++;
this.appendToMessageHistory(dbCursor.getString(2) , dbCursor.getString(3));
dbCursor.moveToNext();
}
}
localstoragehandler.close();
if (msg != null)
{
this.appendToMessageHistory(friend.userName , msg);
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel((friend.userName+msg).hashCode());
}
sendMessageButton.setOnClickListener(new OnClickListener(){
CharSequence message;
Handler handler = new Handler();
public void onClick(View arg0) {
message = messageText.getText();
if (message.length()>0)
{
appendToMessageHistory(imService.getUsername(), message.toString());
localstoragehandler.insert(imService.getUsername(), friend.userName, message.toString());
messageText.setText("");
Thread thread = new Thread(){
public void run() {
try {
if (imService.sendMessage(imService.getUsername(), friend.userName, message.toString()) == null)
{
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
//showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}});
messageText.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (keyCode == 66){
sendMessageButton.performClick();
return true;
}
return false;
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
int message = -1;
switch (id)
{
case MESSAGE_CANNOT_BE_SENT:
message = R.string.message_cannot_be_sent;
break;
}
if (message == -1)
{
return null;
}
else
{
return new AlertDialog.Builder(Messaging.this)
.setMessage(message)
.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
}
})
.create();
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(messageReceiver);
unbindService(mConnection);
FriendController.setActiveFriend(null);
}
#Override
protected void onResume()
{
super.onResume();
bindService(new Intent(Messaging.this, IMService.class), mConnection , Context.BIND_AUTO_CREATE);
IntentFilter i = new IntentFilter();
i.addAction(IMService.TAKE_MESSAGE);
registerReceiver(messageReceiver, i);
FriendController.setActiveFriend(friend.userName);
}
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extra = intent.getExtras();
String username = extra.getString(MessageInfo.USERID);
String message = extra.getString(MessageInfo.MESSAGETEXT);
if (username != null && message != null)
{
if (friend.userName.equals(username)) {
appendToMessageHistory(username, message);
localstoragehandler.insert(username,imService.getUsername(), message);
}
else {
if (message.length() > 15) {
message = message.substring(0, 15);
}
Toast.makeText(Messaging.this, username + " says '"+
message + "'",
Toast.LENGTH_SHORT).show();
}
}
}
};
private MessageReceiver messageReceiver = new MessageReceiver();
public void appendToMessageHistory(String username, String message) {
if (username != null && message != null) {
messageHistoryText.append(username + ":\n");
messageHistoryText.append(message + "\n");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (localstoragehandler != null) {
localstoragehandler.close();
}
if (dbCursor != null) {
dbCursor.close();
}
}
}
logcat message:
if I write text and click on send the application is force closed. I send username, ip and port information to the other activity.
code messageing :
public class Messaging extends Activity {
private static final int MESSAGE_CANNOT_BE_SENT = 0;
public String username;
private EditText messageText;
private EditText messageHistoryText;
private Button sendMessageButton;
private IAppManager imService;
private FriendInfo friend = new ir.android.chat.FriendInfo();
private LocalStorageHandler localstoragehandler;
private Cursor dbCursor;
public static String res="";
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
imService = ((IMService.IMBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
imService = null;
Toast.makeText(Messaging.this, R.string.local_service_stopped,
Toast.LENGTH_SHORT).show();
}
};
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.messaging_screen); //messaging_screen);
messageHistoryText = (EditText) findViewById(R.id.messageHistory);
messageText = (EditText) findViewById(R.id.message);
messageText.requestFocus();
sendMessageButton = (Button) findViewById(R.id.sendMessageButton);
Bundle extras = this.getIntent().getExtras();
friend.userName = extras.getString(FriendInfo.USERNAME);
friend.userNamef = extras.getString(FriendInfo.USERNAMEF);
friend.ip = extras.getString(FriendInfo.IP);
friend.port = extras.getString(FriendInfo.PORT);
String msg = extras.getString(MessageInfo.MESSAGETEXT);
setTitle("Messaging with " + friend.userName);
// EditText friendUserName = (EditText) findViewById(R.id.friendUserName);
// friendUserName.setText(friend.userName);
localstoragehandler = new LocalStorageHandler(this);
dbCursor = localstoragehandler.get(friend.userName, IMService.USERNAME );
if (dbCursor.getCount() > 0){
int noOfScorer = 0;
dbCursor.moveToFirst();
while ((!dbCursor.isAfterLast())&&noOfScorer<dbCursor.getCount())
{
noOfScorer++;
this.appendToMessageHistory(dbCursor.getString(2) , dbCursor.getString(3));
dbCursor.moveToNext();
}
}
localstoragehandler.close();
if (msg != null)
{
this.appendToMessageHistory(friend.userName , msg);
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel((friend.userName+msg).hashCode());
}
sendMessageButton.setOnClickListener(new OnClickListener(){
CharSequence message;
Handler handler = new Handler();
public void onClick(View arg0) {
message = messageText.getText();
if (message.length()>0)
{
//appendToMessageHistory(friend.userNamef, message.toString());
appendToMessageHistory(friend.userNamef, message.toString());
localstoragehandler.insert(friend.userNamef, friend.userName, message.toString());
messageText.setText("");
Thread thread = new Thread(){
public void run() {
try {
if (imService.sendMessage(friend.userNamef, friend.userName, message.toString()) == null)
{
handler.post(new Runnable(){
public void run() {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
//showDialog(MESSAGE_CANNOT_BE_SENT);
}
});
}
} catch (UnsupportedEncodingException e) {
Toast.makeText(getApplicationContext(),R.string.message_cannot_be_sent, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
};
thread.start();
}
}});
messageText.setOnKeyListener(new OnKeyListener(){
public boolean onKey(View v, int keyCode, KeyEvent event)
{
if (keyCode == 66){
sendMessageButton.performClick();
return true;
}
return false;
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
int message = -1;
switch (id)
{
case MESSAGE_CANNOT_BE_SENT:
message = R.string.message_cannot_be_sent;
break;
}
if (message == -1)
{
return null;
}
else
{
return new AlertDialog.Builder(Messaging.this)
.setMessage(message)
.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
/* User clicked OK so do some stuff */
}
})
.create();
}
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(messageReceiver);
unbindService(mConnection);
FriendController.setActiveFriend(null);
}
#Override
protected void onResume()
{
super.onResume();
bindService(new Intent(Messaging.this, IMService.class), mConnection , Context.BIND_AUTO_CREATE);
IntentFilter i = new IntentFilter();
i.addAction(IMService.TAKE_MESSAGE);
registerReceiver(messageReceiver, i);
FriendController.setActiveFriend(friend.userName);
}
public class MessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Bundle extra = intent.getExtras();
String username = extra.getString(MessageInfo.USERID);
String message = extra.getString(MessageInfo.MESSAGETEXT);
if (username != null && message != null)
{
if (friend.userName.equals(username)) {
appendToMessageHistory(username, message);
localstoragehandler.insert(username,friend.userNamef, message);
}
else {
if (message.length() > 15) {
message = message.substring(0, 15);
}
Toast.makeText(Messaging.this, username + " says '"+
message + "'",
Toast.LENGTH_SHORT).show();
}
}
}
};
private MessageReceiver messageReceiver = new MessageReceiver();
public void appendToMessageHistory(String username, String message) {
if (username != null && message != null) {
messageHistoryText.append(username + ":\n");
messageHistoryText.append(message + "\n");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (localstoragehandler != null) {
localstoragehandler.close();
}
if (dbCursor != null) {
dbCursor.close();
}
}
}
log chat :
http://i.stack.imgur.com/USsul.png
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