I'm trying to develop an Android app to receive data from smart insoles through broadcast receiver. I define the broadcast receiver inside the activity. I'm be able to receive the data from onReceive() when I use the LocalBroadcastManager to register the broadcastReceiver. However, I cannot receive any data if I use registerReceiver() to register the broadcastReceiver.
I want to use the registerReceiver() to register the broadcastReceiver since I plan to use handlerThread to let the broadcastReceiver run on a separate thread.
My code are as follows:
public class MoticonActivity extends AppCompatActivity {
private boolean mBound = false;
private boolean standalone = true;
boolean BLE_status = false;
boolean isScanning = false;
private int REQUEST_ENABLE_BT = 1;
private int sensorCount = 0;
private int sensorConnect = 0;
private int leftZeroSuccess = 0;
private int rightZeroSuccess = 0;
private boolean startWrite = false;
private BluetoothLeScanner bluetoothLeScanner;
private List<String> insoleAddressesList = new ArrayList<>();
private List<Service.InsoleDevice> InsoleDeviceList = new ArrayList<>();
private List<String> InsoleAddressList = new ArrayList<>();
private List<Integer> insoleSerialNumbers = new ArrayList<>(Arrays.asList(0, 0));
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 1;
private static final int MY_PERMISSIONS_REQUEST_COARSE_LOCATION = 2;
private static final int MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION = 3;
private static final int MY_PERMISSIONS_REQUEST_BLUETOOTH = 4;
private static final int MY_PERMISSIONS_REQUEST_CONNECT = 5;
private static final int MY_PERMISSIONS_REQUEST_SCAN = 6;
private BufferedWriter file;
private LocationManager locationManager;
private Insole3Service.Insole3Binder mInsole3Service;
private TextView Moticon_filenameDisplay;
private TextView Moticon_logDisplay;
// BroadcastReceiver br = createServiceMsgReceiver();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_moticon);
initiatePermission();
bindService(this, standalone);
// LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(br, new IntentFilter(Insole3Service.BROADCAST_SERVICE_MSG));
registerReceiver(broadcastReceiver, new IntentFilter(Insole3Service.BROADCAST_SERVICE_MSG));
Button button3 = findViewById(R.id.button3);
Button button4 = findViewById(R.id.button4);
Moticon_filenameDisplay = (TextView) findViewById(R.id.Moticonfilename);
Moticon_logDisplay = (TextView) findViewById(R.id.Moticonlog);
Toolbar toolbar2 = findViewById(R.id.toolbar2);
setSupportActionBar(toolbar2);
getSupportActionBar().setTitle("Moticon");
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "start!", Toast.LENGTH_SHORT).show();
startRecoding();
isScanning = true;
scanAndConnection();
}
});
button4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "stop!", Toast.LENGTH_SHORT).show();
stopRecording();
isScanning = false;
Service.StopService stopServiceMessage = Service.StopService.newBuilder().build();
Service.DisconnectInsoles disconnectInsolesMessage = Service.DisconnectInsoles.newBuilder().build();
Service.MoticonMessage stopMoticonMessage = Service.MoticonMessage.newBuilder()
.setStopService(stopServiceMessage)
.setDisconnectInsoles(disconnectInsolesMessage)
.build();
sendProtoToService(stopMoticonMessage.toByteArray());
Log.i("Info","disconnecting...");
}
});
}
private void initiatePermission(){
//PowerManagement permission
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent();
String packageName = getPackageName();
if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
Log.i("Info","disable battery optimization...");
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);
}
}
//BLE permission
boolean bluetoothAvailable = getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE);
if (!bluetoothAvailable) {
Log.i("Bluetooth", "Bluetooth is not supported");
}
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) {
Log.i("Info","Bluetooth not enabled");
// Device doesn't support Bluetooth
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH}, MY_PERMISSIONS_REQUEST_BLUETOOTH);
Log.i("Info", "Bluetooth permission deny...");
return;
} else {
Log.i("info", "BLUETOOTH permission granted");
}
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT}, MY_PERMISSIONS_REQUEST_CONNECT);
Log.i("Info", "Connection permission deny...");
return;
} else {
Log.i("info", "Connection permission granted");
}
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_SCAN}, MY_PERMISSIONS_REQUEST_SCAN);
Log.i("Info", "Bluetooth SCAN permission deny...");
return;
} else {
Log.i("info", "BLUETOOTH SCAN permission granted");
}
//LocationPermission
locationManager = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "First enable FINE LOCATION ACCESS in settings.", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_FINE_LOCATION);
return;
} else {
Log.i("Info", "Fine permission granted");
}
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "First enable COARSE LOCATION ACCESS in settings.", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, MY_PERMISSIONS_REQUEST_COARSE_LOCATION);
return;
} else {
Log.i("Info", "Coarse permission granted");
}
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getApplicationContext(), "First enable BACKGROUND LOCATION ACCESS in settings.", Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION);
return;
} else {
Log.i("Info", "Background permission granted");
}
}
private void scanAndConnection() {
Service.StartInsoleScan startInsoleScanMessage = Service.StartInsoleScan.newBuilder().build();
Service.MoticonMessage moticonMessage1 = Service.MoticonMessage.newBuilder()
.setStartInsoleScan(startInsoleScanMessage)
.build();
sendProtoToService(moticonMessage1.toByteArray());
CompletableFuture.supplyAsync(() -> {
// Process the message
while(InsoleDeviceList.size()<2){
;
}
Service.StopInsoleScan stopInsoleScanMessage = Service.StopInsoleScan.newBuilder().build();
Service.MoticonMessage moticonMessage4 = Service.MoticonMessage.newBuilder()
.setStopInsoleScan(stopInsoleScanMessage)
.build();
sendProtoToService(moticonMessage4.toByteArray());
Log.i("Info","InsoleDeviceList: " + InsoleDeviceList);
Service.ConnectInsoles connectInsolesMessage1 = Service.ConnectInsoles.newBuilder()
.addAllInsoles(InsoleDeviceList)
.build();
Service.MoticonMessage moticonMessage3 = Service.MoticonMessage.newBuilder()
.setConnectInsoles(connectInsolesMessage1)
.build();
sendProtoToService(moticonMessage3.toByteArray());
while (sensorCount < 1) {
;
}
try {
Thread. sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
initiateSensor(insoleSerialNumbers);
return 0;
});
}
private void initiateSensor(List<Integer> SerialNumberList){
Log.i("Info","initating sensors...");
//initiate sensors
Common.ServiceConfig initServiceCfg = Common.ServiceConfig.newBuilder()
.setServiceStartTime(System.currentTimeMillis())
.setServiceId(Common.ServiceId.newBuilder().setLeftSerialNumber(SerialNumberList.get(0)).setRightSerialNumber(SerialNumberList.get(1)).build())
.setServiceType(Common.ServiceType.LIVE)
.setRate(100)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledPressure(true)
.addEnabledAcceleration(true)
.addEnabledAcceleration(true)
.addEnabledAcceleration(true)
.setAccGRange(Common.ServiceConfig.AccGRange.ACC_16_G)
.setAccOdr(Common.ServiceConfig.AccOdr.ACC_208_ODR)
.addEnabledAngular(true)
.addEnabledAngular(true)
.addEnabledAngular(true)
.setAngDpsRange(Common.ServiceConfig.AngDpsRange.ANG_2000_DPS)
.setAngOdr(Common.ServiceConfig.AngOdr.ANG_208_ODR)
.setEnabledTemperature(true)
.setEnabledTotalForce(true)
.setActivityProfile(Common.ServiceConfig.ActivityProfile.ACTIVITY_PROFILE_CONTINUOUS)
.setIsPreview(false)
.build();
Common.MeasurementInfo measurementInfo = Common.MeasurementInfo.newBuilder()
.setName("")
.setComment("")
.build();
Common.ServiceEndpoint endpointCfg = Common.ServiceEndpoint.newBuilder()
.setEndpointType(Common.ServiceEndpoint.EndpointType.APP)
.build();
Common.Zeroing leftZeroingCfg = Common.Zeroing.newBuilder()
.setSource(Common.ZeroingSource.KEEP)
.setMode(Common.ZeroingMode.AUTO)
.setSide(Common.Side.LEFT)
.build();
Common.Zeroing rightZeroingCfg = Common.Zeroing.newBuilder()
.setSource(Common.ZeroingSource.KEEP)
.setMode(Common.ZeroingMode.AUTO)
.setSide(Common.Side.RIGHT)
.build();
// set sensor information
Service.StartService startServiceMessage = Service.StartService.newBuilder()
.setServiceConfig(initServiceCfg)
.setMeasurementInfo(measurementInfo)
.setServiceEndpoint(endpointCfg)
.build();
Service.MoticonMessage leftZeroingMessage = Service.MoticonMessage.newBuilder()
.setZeroing(leftZeroingCfg)
.build();
sendProtoToService(leftZeroingMessage.toByteArray());
Service.MoticonMessage rightZeroingMessage = Service.MoticonMessage.newBuilder()
.setZeroing(rightZeroingCfg)
.build();
sendProtoToService(rightZeroingMessage.toByteArray());
Service.MoticonMessage moticonMessage5 = Service.MoticonMessage.newBuilder()
.setStartService(startServiceMessage)
.build();
sendProtoToService(moticonMessage5.toByteArray());
Log.i("Info: ", "startServiceMessage: " + moticonMessage5);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
BLE_status = true;
Log.i("BLE_status: ", "enabled");
// Bluetooth is now enabled
} else {
// User declined to enable Bluetooth
BLE_status = false;
Log.i("BLE_status: ", "disabled");
}
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
// LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(br);
try {
if(broadcastReceiver != null){
unregisterReceiver(broadcastReceiver);
Log.i("Info","UnregisterReceiver....");
}
} catch (Exception e) {
e.printStackTrace();
}
unbindService();
}
private void startRecoding() {
// Prepare data storage
File directory = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
SimpleDateFormat sdf = new SimpleDateFormat("MMMddyyyyHHmm");
Date currentdate = new Date(System.currentTimeMillis());
String name = "AllData_" + sdf.format(currentdate) + ".csv";
File filename = new File(directory, name);
try {
file = new BufferedWriter(new FileWriter(filename));
} catch (IOException e) {
e.printStackTrace();
}
Moticon_filenameDisplay.setText(name);
}
private void stopRecording() {
Moticon_filenameDisplay.setText("");
}
private boolean bindService(Context context, boolean standalone) {
Intent mIntentInsole3 = new Intent(this, Insole3Service.class);
mIntentInsole3.putExtra("standalone", standalone);
Log.i(TAG, "Start the service");
try {
if (mBound) {
Log.w(TAG, "Service is already bound. Do not bind again");
} else {
context.startService(mIntentInsole3);
Log.i(TAG, "Bind to the service");
context.bindService(mIntentInsole3, mServiceConnection, 0);
mBound = true;
}
} catch (IllegalStateException illegalStateException) {
Log.e(TAG, "Can't bind service as it seems to be in the background: " +
illegalStateException);
}
return mBound;
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("Info", "onServiceConnected");
Log.i("Info","Service type: " + service.getClass().getName());
mInsole3Service = (Insole3Service.Insole3Binder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("Info", "onServiceDisconnected");
mInsole3Service = null;
}
};
private void unbindService() {
Log.i("Info", "Unbind from the service ");
mBound = false;
try {
unbindService(mServiceConnection);
} catch (IllegalArgumentException illegalArgumentException) {
Log.e("Info", "Can't unbind service as it seems not bound: " +
illegalArgumentException);
}
}
private void sendProtoToService(byte[] message) {
try{
Intent broadcast = new Intent(Insole3Service.BROADCAST_CONTROLLER_MSG);
broadcast.putExtra(Insole3Service.EXTRA_PROTO_MSG, message);
// LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcast);
sendBroadcast(broadcast);
Log.i("Info","send Proto: " + message);
}catch(Exception e)
{
Log.e("sendProtoToService","Failed to send proto message",e);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == MY_PERMISSIONS_REQUEST_FINE_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "FINE permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "FINE Location permission denied. You may not be able to use location-related features.", Toast.LENGTH_LONG).show();
}
}
if (requestCode == MY_PERMISSIONS_REQUEST_COARSE_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "COARSE permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "COARSE Location permission denied. You may not be able to use location-related features.", Toast.LENGTH_LONG).show();
}
}
if (requestCode == MY_PERMISSIONS_REQUEST_BACKGROUND_LOCATION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "BACKGROUND permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "BACKGROUND Location permission denied. You may not be able to use location-related features.", Toast.LENGTH_LONG).show();
}
}
if (requestCode == MY_PERMISSIONS_REQUEST_BLUETOOTH) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "Bluetooth permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "Bluetooth permission denied. You may not be able to use bluetooth-related features.", Toast.LENGTH_LONG).show();
}
}
if (requestCode == MY_PERMISSIONS_REQUEST_CONNECT) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "Connection permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "Bluetooth connection denied. You may not be able to use connection-related features.", Toast.LENGTH_LONG).show();
}
}
if (requestCode == MY_PERMISSIONS_REQUEST_SCAN) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.i("Info", "Connection permission granted");
// Permission was granted; you can now use location services
} else {
// Permission was denied; handle it accordingly
Toast.makeText(getApplicationContext(), "Bluetooth connection denied. You may not be able to use connection-related features.", Toast.LENGTH_LONG).show();
}
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
// public BroadcastReceiver createServiceMsgReceiver(){
// return new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Info","broadcast receiver start...");
String action = intent.getAction();
Log.i("Info","Action: " + action);
byte[] protoMsg = intent.getByteArrayExtra(Insole3Service.EXTRA_PROTO_MSG);
try {Service.MoticonMessage moticonMessage = Service.MoticonMessage.parseFrom(protoMsg);
// Log.i("Info","MoticonMessage: " + moticonMessage);
// Continue processing the received message
switch(moticonMessage.getMsgCase()){
case ZEROING_CONF:
Log.i("Info","zeroing: "+ moticonMessage.getZeroingConf().getSide() + " "+ moticonMessage.getZeroingConf().getError());
if (moticonMessage.getZeroingConf().getError().getErrorCode() == Common.ErrorCode.SUCCESS) {
if (moticonMessage.getZeroingConf().getSide() == Common.Side.LEFT) {
leftZeroSuccess = 1;
} else {
rightZeroSuccess = 1;
}
}
if (leftZeroSuccess+rightZeroSuccess==2){
startWrite = true;
}
break;
case TIMESTAMP_CONF:
Log.i("Info","TIMESTAMP!!");
Long Tx = moticonMessage.getTimestampConf().getTimeTx();
Long Rx = moticonMessage.getTimestampConf().getTimeRx();
Log.i("Info","Tx: " + Tx + " " + "Rx: "+ Rx);
break;
case DATA_MESSAGE:
// HANDLE PROTO MESSAGES HERE:
if (startWrite){
Long sensorTime = moticonMessage.getDataMessage().getTime();
String sensorSide = moticonMessage.getDataMessage().getSide().name();
// int sensorSide = moticonMessage.getDataMessage().getSide().getNumber();
List<Float> acc = moticonMessage.getDataMessage().getAccelerationList();
List<Float> gyro = moticonMessage.getDataMessage().getAngularList();
List<Integer> pressure = moticonMessage.getDataMessage().getPressureList();
long phoneTime = System.currentTimeMillis();
write(phoneTime,sensorTime, sensorSide, acc, gyro, pressure);
}
break;
case INSOLE_ADVERTISEMENT:
Log.i("Info","Received advertisement data");
Log.i("Info","device found: "+ InsoleDeviceList.size());
Service.InsoleDevice insoleDevice = moticonMessage.getInsoleAdvertisement().getInsole();
String insoleAddress = insoleDevice.getDeviceAddress();
Common.Side insoleSide = insoleDevice.getSide();
int batteryLevel = moticonMessage.getInsoleAdvertisement().getBatteryLevel();
int insoleSize = insoleDevice.getSize();
if (InsoleDeviceList.size()<2){
if (!InsoleAddressList.contains(insoleAddress)){
InsoleAddressList.add(insoleAddress);
InsoleDeviceList.add(insoleDevice);
if (insoleDevice.getSide().name().equals("LEFT")){
insoleSerialNumbers.set(0,insoleDevice.getSerialNumber());
Log.i("Info","Left found");}
else{
insoleSerialNumbers.set(1,insoleDevice.getSerialNumber());
Log.i("Info","Right found");}
}
}
break;
case INSOLE_CONNECTION_STATUS:
Service.InsoleConnectionStatus.Status sensorConnect = moticonMessage.getInsoleConnectionStatus().getStatus();
if (sensorConnect == Service.InsoleConnectionStatus.Status.READY){
sensorCount += 1;
}
Log.i("Info","connectedSensorCount: "+ sensorConnect + " " + sensorCount);
break;
}
} catch (InvalidProtocolBufferException e) {
// Handle the exception
Log.i("Info","Invalid Protocol Buffer");
}
}
};
// }
private LocationListener locationListener = new LocationListener() {
@Override
public void onLocationChanged(Location location) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private void write(long phoneTime, long sensorTime, String sideSide, List<Float> acc, List<Float> gyro, List<Integer> pressure) {
if (file == null) {
return;
}
String line;
String data = "";
if (acc != null) {
for (Float value : acc) {
data += ", " + value;
}
}
if (gyro != null) {
for (Float value : gyro) {
data += ", " + value;
}
}
if (pressure != null) {
for (Integer value : pressure) {
data += ", " + value;
}
}
line = phoneTime + "," + sensorTime + ", " + sideSide + data + "\n";
try {
file.write(line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Moticon_logDisplay.setText(line);
}
} ```