Iam trying to plot realtime signal from arduino to my android tablet. I've using a potentiometer for testing purpose and ADC sampling rate is 256Hz.
My issue is that the graph plotted on the android app is not smooth. The serial communication is working properly but the plotting is not very good.It feels like the App is lagging and it lags further as the data gets plotted.
Below is the app image
app screenshot
package com.example.ecgauth;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
//import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import com.felhr.usbserial.UsbSerialDevice;
import com.felhr.usbserial.UsbSerialInterface;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.GraphView.GraphViewData;
import com.jjoe64.graphview.GraphView.LegendAlign;
import com.jjoe64.graphview.GraphViewSeries;
import com.jjoe64.graphview.GraphViewSeries.GraphViewStyle;
import com.jjoe64.graphview.LineGraphView;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends Activity implements View.OnClickListener{
private static final String ACTION_USB_PERMISSION = "com.example.ecg.USB_PERMISSION";
TextView hr_value_text;
UsbDevice device;
UsbDeviceConnection connection;
UsbManager usbManager;
UsbSerialDevice serialPort;
PendingIntent pendingIntent;
// private Handler mHandler;
public static final int MESSAGE_FROM_SERIAL_PORT = 0;
final static int gMAX_BLOCKS = 32; //Maximum blocks
final static int gMAX_SAMPLES = 8; //'Maximum samples
final static int gMAX_CHANNELS = 4; //'Maximum channels
final static int gSampFreq = 256; //Sampling frequency
final static int gRawBufferSize = gMAX_BLOCKS * gMAX_SAMPLES ;
final static float swpfactor = 0;
final static int gSec =0;
int sample =0;
private static boolean acq1 = false;
static int block =0;
int g_intRawBuffer[][] = new int[gMAX_BLOCKS][gMAX_SAMPLES];
double g_sngDnOutBuf[] = new double[gMAX_SAMPLES ];
#Override
public void onBackPressed() {
// // TODO Auto-generated method stub
// if (Bluetooth.connectedThread != null) {
// Bluetooth.connectedThread.write("Q");}//Stop streaming
super.onBackPressed();
}
//toggle Button
static boolean Lock;//whether lock the x-axis to 0-5
static boolean AutoScrollX;//auto scroll to the last x value
static boolean Stream;//Start or stop streaming
int old_interval=0;
int new_interval=0;
int mean_interval=20;
//Button init
Button bXminus;
Button bXplus;
ToggleButton tbLock;
ToggleButton tbScroll;
ToggleButton tbStream;
boolean startthread = true;
//GraphView init
static LinearLayout GraphView;
static GraphView graphView;
static GraphViewSeries Series;
//graph value
private static double graph2LastXValue = 0;
private static int Xview=1023;
Button bConnect, bDisconnect;
private TextView connectionstatus;
public int control_a = 0;
public int TotalSample=0;
char chdata = 0;
int i =0;
String finaldata = "";
String rawdata = "";
byte highbyte=0;
int data = 0 ;
int plotdata = 0 ;
int databuff = 0;
public int[] buffer_bt = new int[768];
public int[] copy_buffer_bt = new int[768];
public int ind_bt = 0;
UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { //Defining a Callback which triggers whenever data is read.
#Override
public void onReceivedData(byte[] arg0) {
// lowbyte = arg0;
// highbyte = arg0;
byte[] buffer = arg0;
for (int i = 0; i <= (buffer.length - 1); i++) {
if (buffer[i] != 13) {
if (buffer[i] == 10) {
finaldata = rawdata;
rawdata = "";
} else {
chdata = (char) buffer[i];
rawdata += chdata;
}
}
}
data = Integer.parseInt(finaldata);
mHandler.obtainMessage(MESSAGE_FROM_SERIAL_PORT, data).sendToTarget();
control_a = 1;
buffer_bt[databuff] = data;
// }
//lowbyte = buffer;
//highbyte = buffer;
databuff = databuff + 1;
if (databuff == 767){
databuff=0;
}
//
// for (int uu=0; uu<=767; uu++) {
// copy_buffer_bt[uu] = buffer_bt[uu];
// }
// databuff=0;
// ready_bt=1;
// threadon = true;
// }
}
};
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(broadcastReceiver);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
requestWindowFeature(Window.FEATURE_NO_TITLE);//Hide title
this.getWindow().setFlags(WindowManager.LayoutParams.
FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//Hide Status bar
setContentView(R.layout.activity_main);
//set background color
LinearLayout background = (LinearLayout)findViewById(R.id.bg);
background.setBackgroundColor(Color.BLACK);
// mHandler = new Handler();
//GraphView = (LinearLayout) findViewById(R.id.Graph);
usbManager = (UsbManager) getSystemService(this.USB_SERVICE);
connectionstatus = (TextView) findViewById(R.id.tvBluetooth);
bConnect = (Button)findViewById(R.id.bConnect);
bConnect.setOnClickListener(this);
bDisconnect = (Button)findViewById(R.id.bDisconnect);
bDisconnect.setOnClickListener(this);
//X-axis control button
bXminus = (Button)findViewById(R.id.bXminus);
bXminus.setOnClickListener(this);
bXplus = (Button)findViewById(R.id.bXplus);
bXplus.setOnClickListener(this);
//
tbLock = (ToggleButton)findViewById(R.id.tbLock);
tbLock.setOnClickListener(this);
tbScroll = (ToggleButton)findViewById(R.id.tbScroll);
tbScroll.setOnClickListener(this);
tbStream = (ToggleButton)findViewById(R.id.tbStream);
tbStream.setOnClickListener(this);
//init toggleButton
Lock=true;
AutoScrollX=true;
Stream=true;
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(broadcastReceiver, filter);
init();
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
boolean granted =
intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
if (granted) {
connection = usbManager.openDevice(device);
serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
if (serialPort != null) {
if (serialPort.open()) { //Set Serial Connection Parameters.
//setUiEnabled(true); //Enable Buttons in UI
serialPort.setBaudRate(57600);
serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
serialPort.setParity(UsbSerialInterface.PARITY_NONE);
serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
serialPort.read(mCallback); //
//connectionstatus.setText("Connected");
tvAppend(connectionstatus, " Opened!\n");
} else {
Log.d("SERIAL", "PORT NOT OPEN");
}
} else {
Log.d("SERIAL", "PORT IS NULL");
}
} else {
Log.d("SERIAL", "PERM NOT GRANTED");
}
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
onConnect(bConnect);
} else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
// onClickStop(buttonRestart);
}
}
};
public void onConnect(View view){
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 0x10C4)//Arduino Vendor ID//0x10C4 cp2102 VID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
}
private void tvAppend (TextView tv, CharSequence text){
connectionstatus.setText(" ");
final TextView ftv = tv;
final CharSequence ftext = text;
runOnUiThread(new Runnable() {
#Override
public void run() {
ftv.append(ftext);
}
});
}
void init(){
//Bluetooth.gethandler(mHandler);
//init graphview
GraphView = (LinearLayout) findViewById(R.id.Graph);
// init example series data-------------------
Series = new GraphViewSeries("Signal",
new GraphViewStyle(Color.YELLOW, 2),//color and thickness of the line
new GraphViewData[] {new GraphViewData(0, 0)});
graphView = new LineGraphView(
this // context
, "Electrocardiogram AUTH" // heading
);
graphView.setViewPort(0, Xview);
graphView.setScrollable(true);
graphView.setScalable(false);
graphView.setShowLegend(false);
//graphView.setLegendAlign(LegendAlign.BOTTOM);
graphView.setManualYAxis(true);
graphView.setManualYAxisBounds(2560, 0);
graphView.addSeries(Series); // data
GraphView.addView(graphView);
}
Handler mHandler = new Handler(){
#Override
public void handleMessage(#NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what){
case MESSAGE_FROM_SERIAL_PORT:
plotdata = data;
g_intRawBuffer[block][TotalSample] = plotdata;
TotalSample = TotalSample+1;
if (TotalSample == 8) {
TotalSample = 0;
for (int sample = 0; sample <= (gMAX_SAMPLES - 1); sample++) {
g_sngDnOutBuf[sample] = g_intRawBuffer[block][sample];
}
for (int sample = 0; sample <= (gMAX_SAMPLES - 1); sample++) {
Series.appendData(new GraphViewData(graph2LastXValue, g_sngDnOutBuf[sample]), AutoScrollX);
if (graph2LastXValue >= Xview && Lock == true) {
Series.resetData(new GraphViewData[]{});
graph2LastXValue = 0;
}else
graph2LastXValue += 0.5;
if (Lock == true)
graphView.setViewPort(0, Xview);
else
graphView.setViewPort(graph2LastXValue - Xview, Xview);
//refresh
GraphView.removeView(graphView);
GraphView.addView(graphView);
}
}
}
}
};
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.bConnect:
HashMap<String, UsbDevice> usbDevices = usbManager.getDeviceList();
if (!usbDevices.isEmpty()) {
boolean keep = true;
for (Map.Entry<String, UsbDevice> entry : usbDevices.entrySet()) {
device = entry.getValue();
int deviceVID = device.getVendorId();
if (deviceVID == 0x2341)//Arduino Vendor 2341 ID//0x10C4 cp2102 VID
{
PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
usbManager.requestPermission(device, pi);
keep = false;
} else {
connection = null;
device = null;
}
if (!keep)
break;
}
}
break;
case R.id.bDisconnect:
serialPort.close();
tvAppend(connectionstatus, "Serial Connection Closed!\n");
break;
case R.id.bXminus:
if (Xview<30) Xview++;
break;
case R.id.bXplus:
if (Xview>1) Xview--;
break;
case R.id.tbLock:
if (tbLock.isChecked()){
Lock = true;
}else{
Lock = false;
}
break;
case R.id.tbScroll:
if (tbScroll.isChecked()){
AutoScrollX = true;
}else{
AutoScrollX = false;
}
break;
case R.id.tbStream:
if (tbStream.isChecked()){
serialPort.write("a".getBytes());
}else{
serialPort.write("z".getBytes());
control_a = 0;
}
break;
}
}
}
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 want to destroyed the service. my service is keep running in background.I am calling stopService(Intent intent) method. But it didn't help.
How to bind and unbind the service from another service in android?
Here is my activity. I am started the service i.e SeviceToStartBackgroundService.class from HomeActivity . Here i want to check whether services are running or not if running then i want to stop the services.
package com.example.tracker.activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.tracker.R;
import com.example.tracker.service.BLEService;
import com.example.tracker.service.BackgroundService;
import com.example.tracker.service.BluetoothLeService;
import com.example.tracker.service.SeviceToStartBackgroundService;
public class HomeScreenActivity extends AppCompatActivity {
String TAG="HomeScreenActivity";
public static Intent intent,intent2;
private Intent bluetoothIntent;
int i=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
}
#Override
protected void onResume() {
super.onResume();
stopServiceMethod();
startService(new Intent(getApplicationContext(),SeviceToStartBackgroundService.class));
}
public void stopServiceMethod(){
Log.e(TAG,"stopServiceMethod()");
stopService(new Intent(this, BackgroundService.class));
stopService(new Intent(this, SeviceToStartBackgroundService.class));
stopService(new Intent(this, BluetoothLeService.class));
stopService(new Intent(this, BLEService.class));
}
}
Here is my SeviceToStartBackgroundService.class . When i removed the app from recent apps then the onTaskRemoved(Intent rootIntent) method gets called. And one more service gets started i.e BackgroundService.class.
package com.example.tracker.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class SeviceToStartBackgroundService extends Service {
String TAG="SeviceToStartBService";
private BluetoothLeService mBluetoothLeService;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
Log.e(getClass().getName(), "App just got removed from Recents!");
startService(new Intent(getApplicationContext(),BackgroundService.class));
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Here is my BackgroundService.class . I want to stop this service when app comes in user interaction (front end) .
package com.example.tracker.service;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
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.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
import com.example.tracker.R;
import com.example.tracker.utils.SampleGattAttributes;
import com.example.tracker.utils.SharedPreferencesUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import static android.R.attr.delay;
import static com.shalaka.tracker.constant.SharedFreferencesConstant.KEY_SP_MOBILE_NUMBER;
/**
* Created by greenlantern on 12/9/17.
*/
public class BackgroundService extends Service{
Handler handlerScan=new Handler();
private int scanPeriod;
Context context;
public static String TAG="BackgroundService";
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler = new Handler();
public String[] advDataTypes = new String[256];
ArrayList<BluetoothDevice> bluetoothDeviceArrayList=new ArrayList<>();
ArrayList<BluetoothDevice> bluetoothDeviceArrayListTwo=new ArrayList<>();
private static final int REQUEST_ENABLE_BT = 1;
/*--------------Connect to BLE-----------------------------------------------*/
BluetoothGattService gattService4;
public static ArrayList<BluetoothGattCharacteristic> lastCharacteristic;
// AlertDialog.Builder alertDialog;
private float avgRssi = 0.0f;
// private Dialog dialog;
public static BluetoothLeService mBluetoothLeService;
private boolean mConnected = false;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList();
//service and char uuid
private static final int TRACKER_ON_OFF = 2;
private static final UUID TRACER_TRIPPLE_PRESS_SERVICE=UUID.fromString("edfec62e-9910-0bac-5241-d8bda6932a2f");
private static final UUID TRACKER_TRIPPLE_PRESS_CHAR=UUID.fromString("772ae377-b3d2-4f8e-4042-5481d1e0098c");
private static final UUID IMMEDIATE_ALERT_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
private static final UUID ALERT_LEVEL_UUID = UUID.fromString("00002a06-0000-1000-8000-00805f9b34fb");
public static String connectionStatus;
/*-------------------------------------------------------------------------------*/
public static final String PREFS_NAME = "PreferencesFile";
public String[] mData = new String[400];
/*--------for > 21--------------*/
private BluetoothLeScanner mLEScanner;
private ScanSettings settings;
private List<ScanFilter> filters;
private BluetoothGatt mGatt;
public BackgroundService() {
}
public BackgroundService(Context context) {
this.context = context;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int delay = 10000;
// getting systems default ringtone
handlerScan.postDelayed(new Runnable() {
#Override
public void run() {
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);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_RSSI_UPDATE);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_WRITE_FAILED);
Log.e(TAG,"OnResume()");
getApplicationContext().registerReceiver(mGattUpdateReceiver, intentFilter);
getApplicationContext().bindService(new Intent(getApplicationContext(), BluetoothLeService.class), mServiceConnection, 1);
Toast.makeText(getApplicationContext(),"CALL YOUR METHOD",Toast.LENGTH_LONG).show();
// 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(context, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
}
// 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) {
Toast.makeText(context, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
return;
}
for (int i = 0; i < 256; i += REQUEST_ENABLE_BT) {
advDataTypes[i] = "Unknown Data Type";
}
advDataTypes[REQUEST_ENABLE_BT] = "Flags";
advDataTypes[2] = "Incomplete List of 16-bit Service Class UUIDs";
advDataTypes[3] = "Complete List of 16-bit Service Class UUIDs";
advDataTypes[4] = "Incomplete List of 32-bit Service Class UUIDs";
advDataTypes[5] = "Complete List of 32-bit Service Class UUIDs";
advDataTypes[6] = "Incomplete List of 128-bit Service Class UUIDs";
advDataTypes[7] = "Complete List of 128-bit Service Class UUIDs";
advDataTypes[8] = "Shortened Local Name";
advDataTypes[9] = "Complete Local Name";
advDataTypes[10] = "Tx Power Level";
advDataTypes[13] = "Class of LocalDevice";
advDataTypes[14] = "Simple Pairing Hash";
advDataTypes[15] = "Simple Pairing Randomizer R";
advDataTypes[16] = "LocalDevice ID";
advDataTypes[17] = "Security Manager Out of Band Flags";
advDataTypes[18] = "Slave Connection Interval Range";
advDataTypes[20] = "List of 16-bit Solicitaion UUIDs";
advDataTypes[21] = "List of 128-bit Solicitaion UUIDs";
advDataTypes[22] = "Service Data";
advDataTypes[23] = "Public Target Address";
advDataTypes[24] = "Random Target Address";
advDataTypes[25] = "Appearance";
advDataTypes[26] = "Advertising Interval";
advDataTypes[61] = "3D Information Data";
advDataTypes[255] = "Manufacturer Specific Data";
scanPeriod = getApplicationContext().getSharedPreferences(PREFS_NAME, 0).getInt("scan_interval", 2000);
scanLeDevice(true);
}
// unRegisterReceicerAndService();
}, 1000);
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
// -------------------Connect Ble--------------------------------------
}
private void scanLeDevice(final boolean enable) {
Log.e(TAG,"scanTrackerDevices");
bluetoothDeviceArrayList.clear();
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
int arraySize=bluetoothDeviceArrayListTwo.size();
Log.e(TAG,"bluetoothDeviceArrayListTwo Size in scan :"+arraySize);
for (int i=0;i<bluetoothDeviceArrayListTwo.size();i++){
BluetoothDevice bluetoothDevice=bluetoothDeviceArrayListTwo.get(i);
Log.e(TAG,"Device Name in scan :"+bluetoothDevice.getName());
Log.e(TAG,"Device Address in scan :"+bluetoothDevice.getAddress());
if (i==0){
mBluetoothLeService.connect(bluetoothDevice.getAddress());
}
}
}
}, scanPeriod);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
String d = "";
String rd = "";
String h = "0123456789ABCDEF";
int ln = 0;
int i = 0;
while (i < scanRecord.length) {
int x = scanRecord[i] & 255;
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
if (i == ln) {
ln = (i + x) + REQUEST_ENABLE_BT;
if (x == 0) {
break;
}
d = new StringBuilder(String.valueOf(d)).append("\r\n Length: ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
i += REQUEST_ENABLE_BT;
x = scanRecord[i] & 255;
d = new StringBuilder(String.valueOf(d)).append(", Type :").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).append(" = ").append(advDataTypes[x]).append(", Value: ").toString();
rd = new StringBuilder(String.valueOf(rd)).append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) + REQUEST_ENABLE_BT)).toString();
} else {
d = new StringBuilder(String.valueOf(d)).append(" ").append(h.substring(x / 16, (x / 16) + REQUEST_ENABLE_BT)).append(h.substring(x % 16, (x % 16) +REQUEST_ENABLE_BT)).toString();
}
i += REQUEST_ENABLE_BT;
}
Log.e(TAG,"UUID : "+device.getUuids());
String[] arrayDeviceName=String.valueOf(device.getName()).split(" ");
String deviceName0=arrayDeviceName[0];
// String deviceName1=arrayDeviceName[1];
if (deviceName0.equals("EUROtronic")){
Log.e(TAG,"Device Name :"+device.getName());
bluetoothDeviceArrayListTwo.add(device);
// Log.e(TAG,"Device Address :"+deviceName0);
}
}
};
/*-------------------Connect BLE---------------------------------------------*/
private Handler mHandler2=new Handler();;
public final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))
{
numberOfRssi = 0;
avgRssi = 0.0f;
mConnected = true;
mHandler2.postDelayed(startRssi, 300);
Log.e(TAG,"ACTION_GATT_CONNECTED");
}
else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
Log.e(TAG,"ACTION_GATT_DISCONNECTED");
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
displayGattServicesForDimmer(mBluetoothLeService.getSupportedGattServices());
Log.e(TAG,"ACTION_GATT_SERVICES_DISCOVERED");
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
Log.e(TAG,"ACTION_DATA_AVAILABLE");
String unknownServiceString = context.getResources().getString(R.string.unknown_service);
displayDimmer2(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
} else if (BluetoothLeService.ACTION_GATT_RSSI_UPDATE.equals(action)) {
} else if (BluetoothLeService.ACTION_GATT_WRITE_FAILED.equals(action)) {
Log.e(TAG,"ACTION_GATT_WRITE_FAILED");
}
}
};
private BluetoothGattCharacteristic mNotifyCharacteristic;
public static ServiceConnection mServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e(TAG, "Unable to initialize Bluetooth");
// getActivity().finish();
}
// mBluetoothLeService.connect(mDeviceAddress);
}
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
private boolean notificationActive = true;
private int numberOfRssi = 0;
private Runnable startRssi = new Runnable() {
public void run() {
if (mConnected) {
mBluetoothLeService.readRemoteRssi();
mHandler2.postDelayed(startRssi, 200);
}
}
};
public BluetoothGatt getmGatt() {
return mGatt;
}
private void displayDimmer2(String data){
if (data!=null){
Log.e(TAG,"display Dimmer2"+data);
String sosString = data.substring(0, Math.min(data.length(), 3));
Log.e(TAG,"SOS String :"+sosString);
if (sosString.equals("SOS")){
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+ SharedPreferencesUtils.getStringFromSharedPreferences(KEY_SP_MOBILE_NUMBER,getApplicationContext())));
callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(callIntent);
}
}
}
/*-------------------------disaplay gatt service for dimmer----------------------*/
private void displayGattServicesForDimmer(List<BluetoothGattService> gattServices) {
if (gattServices != null) {
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList();
this.mGattCharacteristics = new ArrayList();
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap();
String uuid = gattService.getUuid().toString();
currentServiceData.put("NAME", SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put("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("NAME", "\t\t\t<<" + SampleGattAttributes.lookup(uuid, unknownCharaString) + ">>");
currentCharaData.put("UUID", "\t\t\tUUID: 0x" + uuid.substring(4, 8) + ", Properties: " + translateProperties(gattCharacteristic.getProperties()));
gattCharacteristicGroupData.add(currentCharaData);
Log.i(TAG,"CUrrent CHARACTERISTIC DATA"+currentCharaData);
Log.i(TAG,"UUID : "+uuid.substring(4, 8));
Log.i(TAG,"Proprties : "+gattCharacteristic.getProperties());
Log.i(TAG,"Translate Proprties : "+translateProperties(gattCharacteristic.getProperties()));
Log.i(TAG,"char list"+gattCharacteristicData.toString());
}
gattService4=gattService;
this.mGattCharacteristics.add(charas);
}
if (mGattCharacteristics.get(3)!=null) {
lastCharacteristic = new ArrayList<>(mGattCharacteristics.get(3));
enableNotifyOfCharcteristicForDimmer(lastCharacteristic);
}
}
}
private String translateProperties(int properties) {
String s = "";
if ((properties & 1) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Broadcast").toString();
}
if ((properties & 2) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Read").toString();
}
if ((properties & 4) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/WriteWithoutResponse").toString();
}
if ((properties & 8) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Write").toString();
}
if ((properties & 16) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Notify").toString();
}
if ((properties & 32) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/Indicate").toString();
}
if ((properties & 64) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/SignedWrite").toString();
}
if ((properties & 128) > 0) {
s = new StringBuilder(String.valueOf(s)).append("/ExtendedProperties").toString();
}
if (s.length() > 1) {
return s.substring(1);
}
return s;
}
// Enable Characteristic for dimmer
public void enableNotifyOfCharcteristicForDimmer(ArrayList<BluetoothGattCharacteristic> lastCharacteristic){
if(mGattCharacteristics!=null) {
checkCharacteristicPresent(lastCharacteristic.get(0));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(0), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+0+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 0 +" :" +lastCharacteristic.get(0).toString());
checkCharacteristicPresent(lastCharacteristic.get(1));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(1), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+1+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 1 +" :" +lastCharacteristic.get(1).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
checkCharacteristicPresent(lastCharacteristic.get(3));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(3), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+3+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 3 +" :" +lastCharacteristic.get(3).toString());
checkCharacteristicPresent(lastCharacteristic.get(4));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(4), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+4+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 4 +" :" +lastCharacteristic.get(4).toString());
checkCharacteristicPresent(lastCharacteristic.get(5));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(5), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+5+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 5 +" :" +lastCharacteristic.get(5).toString());
checkCharacteristicPresent(lastCharacteristic.get(2));
mBluetoothLeService.setCharacteristicNotification(lastCharacteristic.get(2), true);
notificationActive = true;
Log.e(TAG,"Characteristic index : "+2+":\nM GATT CHARACTERISTIC AT "+"Service 4 : CHAR"+ 2 +" :" +lastCharacteristic.get(2).toString());
}
}
// Check the type of characteristic i.e READ/WRITE/NOTIFY
public void checkCharacteristicPresent(BluetoothGattCharacteristic characteristic) {
int charaProp = characteristic.getProperties();
Log.e(TAG, "checkCharacteristicPresent Prop : " + charaProp);
mBluetoothLeService.setCurrentCharacteristic(characteristic);
if ((charaProp & 2) > 0) {
Log.e(TAG, "CharProp & 2 : " + charaProp);
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & 16) > 0) {
Log.e(TAG, "CharProp & 16 : " + charaProp);
mNotifyCharacteristic = characteristic;
} else {
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
}
if ((charaProp & 8) > 0 || (charaProp & 4) > 0) {
Log.e(TAG, "CharProp & 4 : " + charaProp);
} else {
Log.e(TAG, "Else : " + charaProp);
}
}
public void disconnectBLEDevice(){
// if (mNotifyCharacteristic != null) {
mBluetoothLeService.disconnect();
// }
}
#Override
public void onDestroy(){
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show();
super.onDestroy();
}
}
You are using service as START_STICKY, i.e it run forever even after application is kill(Unless it is killed by the System), Later the system will try to re-create the sticky service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) method. And as i can see its not a binded service.
So what you can do to kill it :
1.Take the Service class reference and call a stop method on it .And validate in onStartCommand.
public void destroyService() {
stopSelf();
}
2. As documentation says the OnStartCommand is guaranteed to call for each startServiceMethod() so you can just pass a flag to stop it.
private void stopService() {
Intent intent = new Intent(this, Background.class);
intent.putExtra("close", true);
startService(intent);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.hasExtra("close") && intent.getBooleanExtra("close",false)) {
stopSelf();
} else {
// Do your work here
}
return START_STICKY;
}
Also Read the Service documentation here, for your need .
Operations inside service are asynchronous that's why calling unbindService or stopService don't finish immediatelly.
If you still need to stop long running operation inside, I suggest you to create your own method inside a service where you stop your operations.
I am creating an android app in which I want to put clock ticking sound in the background and that too for last few seconds.
the audio is for 21 sec and i too want it to be played in last 21 seconds of the timer. The actual timer is running for 2 minutes.
I was trying the following code :
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
millis = millisUntilFinished;
if(millis == 21000){
mp1.start();
}
hms = String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
timer.setText(hms);
}
where mp1 is :
mp1 = MediaPlayer.create(AnimalMain.this,R.raw.tick_tock);
But nothing is getting played. Also, I am getting the error in the log cat as :
should have subtitle controller already set
I tried many of the stackoverflow links with the same issue but could not resolve it using them. Please Help.
For any reference, please see the entire code here:
package com.example.jumboquest;
import android.app.Activity;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.CountDownTimer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import android.media.MediaPlayer;
public class AnimalMain extends Activity {
TextView timer, roundStatus;
ListView jum;
ProgressBar prog;
EditText ans;
ToggleButton pause;
String s,hms,hmso;
int[] a;
Button next;
static long millis;
static CountDownTimer t;
long toggleValue;
String[] s1 = new String[4];
static ArrayList<String> words;
static ArrayAdapter<String> aa;
static int progressStatus = 0;
//Button match;
static long resumeTsp;
static boolean phoneRinging = false;
static int scorekeeper;
static int rnd_counter;
boolean bonus = false;
long bonus_millis = 0;
MediaPlayer mp1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
rnd_counter++;
setContentView(R.layout.screen2);
resumeTsp = 120000;
jum = (ListView)findViewById(R.id.jum);
ans = (EditText)findViewById(R.id.ans);
timer = (TextView)findViewById(R.id.timer);
roundStatus = (TextView)findViewById(R.id.desc);
prog = (ProgressBar)findViewById(R.id.prog);
//match = (Button) findViewById(R.id.button1);
mp1 = MediaPlayer.create(AnimalMain.this,R.raw.tick_tock);
roundStatus.setText("Round:" +rnd_counter);
Intent intnt = getIntent();
progressStatus = intnt.getIntExtra("prog", 0);
new Thread(new Runnable(){
public void run(){
prog.setProgress(progressStatus);
try{
Thread.sleep(5000);
}
catch(Exception e){
e.printStackTrace();
}
}
}).start();
// Create the array list of to do items
words = new ArrayList<String>();
// Create the array adapter to bind the array to the listview
aa = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,words);
// Bind the array adapter to the listview.
jum.setAdapter(aa);
InputStream i = this.getResources().openRawResource(R.raw.first_round);
String line = null;
int currentLineNo = 1;
int min = 1;
int max = 49;
int startLine = 0;
int endLine = 0;
Random rand = new Random();
switch(rnd_counter){
case 1:
min = 1;
max = 28;
break;
case 2:
min = 32;
max = 59;
break;
case 3:
min = 63;
max = 92;
break;
}
int r = rand.nextInt((max - min) + 1) + min;
startLine = r;
endLine = r+3;
BufferedReader in = null;
try {
in = new BufferedReader (new InputStreamReader(i));
//read to startLine
while(currentLineNo<startLine) {
if (in.readLine()==null) {
// oops, early end of file
throw new IOException("File too small");
}
++currentLineNo;
}
int i1=0;
//read until endLine
while(currentLineNo<=endLine) {
line = in.readLine();
if (line==null) {
// here, we'll forgive a short file
// note finally still cleans up
return;
}
s1[i1]=line;
//= new StringBuffer(line).reverse().toString();
List<Character> jumble = new ArrayList<Character>();
StringBuilder sample = new StringBuilder(line.length());
for(char c : line.toCharArray()){
jumble.add(c);
}
//int flag_first = 0;
while(jumble.size() != 0){
int rnd = (int)(Math.random()*jumble.size());
if(rnd == 0 && jumble.size() == line.length()){
continue;
}
else{
sample.append(jumble.remove(rnd));
}
}
words.add(sample.toString());
aa.notifyDataSetChanged();
++i1;
++currentLineNo;
}
} catch (IOException ex) {
System.out.println("Problem reading file.\n" + ex.getMessage());
} finally {
try { if (in!=null) in.close(); } catch(IOException ignore) {}
}
a = new int[4];
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
/* match.setOnClickListener(new OnClickListener(){
public void onClick(View v){
String answer = ans.getText().toString();
if(answer.equalsIgnoreCase(s1[0])){
words.remove(0);
aa.notifyDataSetChanged();
words.add(0,answer);
aa.notifyDataSetChanged();
}
else if(answer.equalsIgnoreCase(s1[1])){
words.remove(1);
aa.notifyDataSetChanged();
words.add(1,answer);
aa.notifyDataSetChanged();
}
else if(answer.equalsIgnoreCase(s1[2])){
words.remove(2);
aa.notifyDataSetChanged();
words.add(2,answer);
aa.notifyDataSetChanged();
}
else if(answer.equalsIgnoreCase(s1[3])){
words.remove(3);
aa.notifyDataSetChanged();
words.add(3,answer);
aa.notifyDataSetChanged();
}
}
});*/
jum.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
String selected = jum.getItemAtPosition(arg2).toString();
s= ans.getText().toString();
if(s.equals(s1[arg2]))
{
a[arg2]=1;
//Toast.makeText(getApplicationContext(), "CORRECT!! Now Crack the Next One.. :) ", Toast.LENGTH_SHORT).show();
words.remove(arg2);
aa.notifyDataSetChanged();
words.add(arg2,s);
aa.notifyDataSetChanged();
arg1.setEnabled(false);
ans.setText("");
if(a[0]==1 && a[1]==1 && a[2]==1 && a[3]==1)
{
t.cancel();
if(millis >= 60000){
bonus = true;
bonus_millis = (millis/1000)-60;
}
//scorekeeper += 40;
Intent i=new Intent(getApplicationContext(), AnimalDatabase.class);
i.putExtra("milli", millis);
i.putExtra("score", scorekeeper);
i.putExtra("bonus", bonus);
i.putExtra("round", rnd_counter);
i.putExtra("bonus_score",bonus_millis);
//i.putExtra("progress",progressStatus);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
//Toast.makeText(getApplicationContext(), "WELL DONE!! All the best for the quiz :) ", Toast.LENGTH_LONG).show();
// finish();
}
}
else
{
ans.setText(s);
Toast.makeText(getApplicationContext(), "INCORRECT :( Try Again.. ", Toast.LENGTH_SHORT).show();
}
}
});
TelephonyManager telephonyManager =
(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener callStateListener = new PhoneStateListener() {
public void onCallStateChanged(int state, String incomingNumber)
{
if(state==TelephonyManager.CALL_STATE_RINGING){
resumeTsp = millis;
t.cancel();
timer.setText("Game Paused!");
Toast.makeText(getApplicationContext(),"Phone Is Riging",
Toast.LENGTH_LONG).show();
}
if(state==TelephonyManager.CALL_STATE_OFFHOOK){
Toast.makeText(getApplicationContext(),"Phone is Currently in A call",
Toast.LENGTH_LONG).show();
}
if(state==TelephonyManager.CALL_STATE_IDLE){
t = new StartTimer(resumeTsp,1000);
t.start();
}
}
};
telephonyManager.listen(callStateListener,PhoneStateListener.LISTEN_CALL_STATE);
}
#Override
public void onBackPressed(){
return;
}
class StartTimer extends CountDownTimer{
public StartTimer(long duration, long interval){
super(duration, interval);
}
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
millis = millisUntilFinished;
//if(millis == 21000){
// Toast.makeText(getApplicationContext(), String.valueOf(millis), Toast.LENGTH_SHORT).show();
// mp1.start();
//}
hms = String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));
timer.setText(hms);
}
#Override
public void onFinish() {
//time up
phoneRinging = false;
timer.setText("TIME UP!");
mp1.stop();
ans.setEnabled(false);
for(int j = 0; j<4;j++){
timer.setText("SOLUTION:");
words.remove(j);
aa.notifyDataSetChanged();
words.add(j,s1[j]);
aa.notifyDataSetChanged();
}
}
}
}
It can be done by simply adding delay instead of checking timer value in the OnTick() which will not work. The delay can be added in the following way :
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do something after 5s = 5000ms
mp1.start();
mp1.setLooping(true);
}
}, 100000);
put the delay after which you want to start the audio in background and it worked in my case.
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);
}
I am sending some data to an android application over UDP. Therefore i created the following UDPReceiver-Class:
package com.example.urowatch;
import java.net.*;
import java.nio.ByteBuffer;
import java.io.*;
public class UDPReceiver extends Thread
{
private DatagramSocket m_Socket;
private int m_BufferSize;
private Boolean m_End = false;
private int m_TotalLength;
private int m_Received;
private byte[] m_Buffer;
private byte[] m_Result;
private Boolean m_IsNewResult = false;
private float m_Progress;
private int m_ImageCount = 0;
private int m_FrameErrors = 0;
public UDPReceiver(String name, int port, int bufferSize) throws IOException
{
super(name);
m_Socket = new DatagramSocket(port);
m_BufferSize = bufferSize;
m_Socket.setBroadcast(true);
m_Socket.setReceiveBufferSize(m_BufferSize);
}
public void run()
{
while(!m_End)
{
try
{
byte[] buf = new byte[m_BufferSize];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
m_Socket.receive(packet);
ProcessData(packet);
}
catch (IOException e)
{
if (!m_Socket.isClosed())
e.printStackTrace();
}
}
}
private void ProcessData(DatagramPacket packet)
{
if (packet.getLength() == 4)
{
ByteBuffer bb = ByteBuffer.wrap(packet.getData());
m_TotalLength = bb.getInt();
if (m_Received != 0)
m_FrameErrors++;
m_Received = 0;
m_Buffer = new byte[m_TotalLength];
}
else if (m_Buffer != null && m_Received != m_TotalLength)
{
int length = packet.getLength();
System.arraycopy(packet.getData(), 0, m_Buffer, m_Received, length);
m_Received += length;
m_Progress = 100 * (float)m_Received/(float)m_TotalLength;
if (m_Received == m_TotalLength)
{
m_Result = new byte[m_TotalLength];
System.arraycopy(m_Buffer, 0, m_Result, 0, m_TotalLength);
m_IsNewResult = true;
m_ImageCount++;
m_Received = 0;
}
}
}
public Boolean IsNewResult()
{
return m_IsNewResult;
}
public byte[] GetResult()
{
m_IsNewResult = false;
return m_Result;
}
public float GetProgress()
{
return m_Progress;
}
public float GetRatio()
{
return 100 * (float)m_ImageCount / (float)m_FrameErrors;
}
public void stopServer()
{
m_End = true;
if (m_Socket != null)
m_Socket.close();
}
}
And i am using this class like this:
package com.example.urowatch;
import java.io.IOException;
import java.text.DecimalFormat;
import android.os.*;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
public class LiveActivity extends Activity {
private static ImageView m_ImageView1;
private static TextView m_TextView1;
private static DecimalFormat m_DF;
private static Context m_Context;
private UDPReceiver m_Receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
// Show the Up button in the action bar.
setupActionBar();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
m_ImageView1 = (ImageView)findViewById(R.id.imageView1);
m_TextView1 = (TextView)findViewById(R.id.textView1);
m_Context = this;
m_DF = new DecimalFormat("00.00");
}
/**
* Set up the {#link android.app.ActionBar}, if the API is available.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.live, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. Use NavUtils to allow users
// to navigate up one level in the application structure. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
NavUtils.navigateUpFromSameTask(this);
return true;
}
return super.onOptionsItemSelected(item);
}
private static Handler MyHandler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
if (msg.what == 100)
{
float[] infos = (float[])msg.obj;
m_TextView1.setText("Empfange Bild: " + m_DF.format(infos[0]) + "% (FrameErrors: " + m_DF.format(infos[1]) + "%)");
}
else if (msg.what == 101)
{
byte[] b = (byte[])msg.obj;
m_TextView1.setText("Empfange Bild: 100,00%");
m_ImageView1.setImageBitmap(BitmapFactory.decodeByteArray(b, 0, b.length));
}
else if (msg.what == 102)
{
AlertDialog.Builder b = new AlertDialog.Builder(m_Context);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + (Exception)msg.obj);
b.setNeutralButton("OK", null);
b.show();
}
}
};
#Override
public void onBackPressed() {
super.onBackPressed();
if (m_Receiver != null)
m_Receiver.stopServer();
finish();
}
#Override
public void onPause()
{
m_Receiver.stopServer();
super.onPause();
}
#Override
protected void onResume()
{
try {
m_Receiver = new UDPReceiver("UDPReceiver", 5678, 1024);
m_Receiver.start();
} catch (IOException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle("Fehler");
b.setMessage("Es ist folgende Exception aufgetreten:\n" + e1);
b.setNeutralButton("OK", null);
b.show();
}
// Thread thread = new Thread()
// {
// #Override
// public void run()
// {
// while(true)
// {
// try {
//sleep(250);
Toast.makeText(getBaseContext(), "Runing Thread", Toast.LENGTH_SHORT).show();
Update();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// MyHandler.sendMessage(MyHandler.obtainMessage(102, e));
// }
// }
// }
// };
// thread.start();
super.onResume();
}
public void buttonClick(View v)
{
Update();
}
private void Update()
{
if (m_Receiver != null)
{
if (m_Receiver.IsNewResult())
{
byte[] b = m_Receiver.GetResult();
MyHandler.sendMessage(MyHandler.obtainMessage(101, b));
}
else
{
float[] infos = new float[2];
infos[0] = m_Receiver.GetProgress();
infos[1] = m_Receiver.GetRatio();
MyHandler.sendMessage(MyHandler.obtainMessage(100, infos));
}
}
}
}
As you see i want to check the status of the UDPReceiver-Object (Is there a new complete byte[] ready?) by a thread. To update the GUI, the thread has to send a Message to MyHandler which will update the GUI.
In the moment i have to to click a button to raise the buttonClick-Event. Later on i want to do this in the commented thread-structure.
Now, here's my problem:
I start the Activity and everything works fine. Then i am starting to send ONE packet manually with my UDP-Sender (which works, i validated it with a C#-UDP-Receiver). The first packet get received fine. Then i send the second packet which get received, too. But from now on, my breakpoint at m_Socket.receive(packet); wont get hit anymore!
I have NO idea what this behaviour causes and it is very important for me to make this application work.
Please, if you have ANY Idea or just a guess, please let me know.