I want to build an application that start a Service. This Service can run also if the APP is closed.
So I'm building this code on the OnCreate method of my BLEActivity.java:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble);
startService(new Intent(this, BlePowerService.class));
}
Now I want that this service shoudl to start every 5 minutes also if the APP is closed.
The correct way to do this, is to create a Thread into BlePowerService ?
So I'm building this:
public class BlePowerService extends Service {
public DbLayer db;
Setting settingApp;
List<ScanFilter> filters;
String[] stringSequence = new String[] {CHARACTERISTIC_FORZA_STRING};
BluetoothAdapter mBluetoothAdapter;
BluetoothGatt mGatt;
BluetoothDevice currDevice;
static final long SCAN_PERIOD = 1000;
BluetoothLeScanner mLEScanner;
Handler mHandler;
int ReadQueueIndex;
List<BluetoothGattCharacteristic> ReadQueue;
ScanSettings settings;
int id = 1000;
boolean valore;
//String UuID = "f0001132-0451-4000-b000-000000000000";
String LOG_CODE = "NOTIFSRV";
int NOTIFICATION_GREEN = 1;
int NOTIFICATION_RED = 2;
int START_HOUR = 7;
int RANGE_HOURS_WEIGHT = 13;
int START_NOTIFY = 9;
int END_NOTIFY = 21;
public static String PAR_NOTIFICATION_EXERCISEID = "parNotificationExerciseId";
String NEW_ACTIVITY_START = "NAS";
String OPEN_ACTIVITY_START = "OAS";
public BlePowerService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
return null;
}
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onCreate() {
super.onCreate();
mHandler = new Handler();
Context sharedContext = null;
try {
sharedContext = this.createPackageContext(
"com.eresult.diabesitycare.devicesensor",
Context.CONTEXT_INCLUDE_CODE);
if (sharedContext == null) {
return;
}
db=new DbLayer(sharedContext);
db.open();
} catch (Exception e) {
String error = e.getMessage();
// Log.d(LOG_CODE,"DB error : " + error);
return;
}
}
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
//RECUPERO LE IMPOSTAZIONI SETTATE DALL'UTENTE
settingApp = db.fetchSetting();
mTimer = new Timer();
mTimer.schedule(timerTask, 2500, 1 * 60 * 1000);
} catch (Exception e) {
// Log.e("POWER_SERVICE", e.getMessage());
}
return super.onStartCommand(intent, flags, startId);
}
private Timer mTimer;
TimerTask timerTask = new TimerTask() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void run() {
//LEGGO TUTTI I DATI DAL SENSORE FINCHE CI SONO VALORI
valore = true;
int conta = 0;
while(valore){
conta++;
Log.v("CICLO WHILE", conta+"");
if (currDevice != null) {
GattClientCallback gattClientCallback = new GattClientCallback();
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
scanLeDevice(false);// will stop after first device detection
}else{
//provo a ricollegarmi al dispositivo probabile, abbia perso la connessione con esso
scanLeDevice(true);
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void connectToDevice(BluetoothDevice device) {
//VERIFICO SE IL DEVICE è QUELLO CHE VOGLIO IO
if (mGatt == null && settingApp != null
&& device.getAddress().equals(settingApp.getAddressBleSX())) {
currDevice = device;
GattClientCallback gattClientCallback = new GattClientCallback();
mGatt = currDevice.connectGatt(getBaseContext(), false, gattClientCallback);
scanLeDevice(false);// will stop after first device detection
}
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi,
byte[] scanRecord) {
Handler h = new Handler(getApplicationContext().getMainLooper());
// Although you need to pass an appropriate context
//TO DO
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void scanLeDevice(final boolean enable) {
//TO DO
}
private ScanCallback mScanCallback = new ScanCallback() {
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public void onScanResult(int callbackType, ScanResult result) {
//TODO
}
};
#RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private class GattClientCallback extends BluetoothGattCallback {
#SuppressLint("LongLogTag")
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
try{
//TODO
}catch(Exception e){
Log.e("ON_CONNECTION_STATE_CHANGE", e.getMessage());
}
}
public void disconnectGattServer() {
valore = false;
if (mGatt != null) {
mGatt.disconnect();
mGatt.close();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
//TODO
}
private void ReadCharacteristics(int index) {
mGatt.readCharacteristic(ReadQueue.get(index));
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
// Log.i("INFO", "Characteristic changed, " + characteristic.getUuid().toString());
readCharacteristic(characteristic);
}
private void enableCharacteristicNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
//TODO
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
//TODO
}
}
}
Related
This is my first app working with Bluetooth in Androind and I'm having a kinda unique problem: the bluetooth receiver isn't working on the device that is advertising the bluetooth service.
I have tested the application in 2 phones at the same time (I'll call them phone A and B to explain better). At first I start the advertising with the phone A, then I start the discovery with the phone B and finally I press the button in phone B to send data. This button should first start the Gatt connection and if it's working it should then broadcast a message that confirms the connection. To see it I have used a Log in the Broadcast receiver but the result I get is this messsagge appearing only in the logcat of the phone B but not on the one of phone A.
I have looked at a lot of examples and post on Stackoverflow but I can't seem to find the solution to this problem.
So I really can't find what the real problem here is. Maybe I'm just using badly the Bluetooth classes or I just lack knowledge. In any case, here there is all the code of the MainActivity as it is the only class of this simple project.
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mText;
private Button mAdvertiseButton;
private Button mDiscoverButton;
private Button mSendButton;
private String TAG = "INFOBLERESULTS";
private BluetoothLeScanner mBluetoothLeScanner;
private BluetoothDevice bluetoothDevice;
private Handler mHandler = new Handler();
private ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
Log.d(TAG, result.getDevice().getAddress());
super.onScanResult(callbackType, result);
if( result == null
|| result.getDevice() == null
|| TextUtils.isEmpty(result.getDevice().getAddress()) )
return;
StringBuilder builder = new StringBuilder( result.getDevice().getAddress() );
builder.append("\n").append(result.getDevice().getName());
//builder.append("\n").append(new String(result.getScanRecord().getServiceData(result.getScanRecord().getServiceUuids().get(0)), Charset.forName("UTF-8")));
mText.setText(builder.toString());
bluetoothDevice = result.getDevice();
bluetoothLeService = new BluetoothLeService();
bluetoothLeService.setAddress(result.getDevice().getAddress());
}
#Override
public void onBatchScanResults(List<ScanResult> results) {
super.onBatchScanResults(results);
}
#Override
public void onScanFailed(int errorCode) {
Log.e( TAG, "Discovery onScanFailed: " + errorCode );
super.onScanFailed(errorCode);
}
};
private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private boolean connected = false;
//Inner classes
class BluetoothLeService extends Service {
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
private static final int STATE_DISCONNECTED = 0;
private static final int STATE_CONNECTED = 2;
private int connectionState;
public Context ctx;
protected BluetoothGatt bluetoothGatt;
protected final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
Log.i(TAG, "GATT status = "+ status + " newState = " + newState);
if(status == BluetoothGatt.GATT_SUCCESS){
if (newState == BluetoothProfile.STATE_CONNECTED) {
// successfully connected to the GATT Server
connectionState = STATE_CONNECTED;
broadcastUpdate(ACTION_GATT_CONNECTED);
bluetoothGatt = gatt;
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
// disconnected from the GATT Server
connectionState = STATE_DISCONNECTED;
broadcastUpdate(ACTION_GATT_DISCONNECTED);
gatt.close();
}
}else{
gatt.close();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(
BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status
) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onCharacteristicChanged(
BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic
) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
private Binder binder = new LocalBinder();
private String address = "";
public void setAddress(String address) {
this.address = address;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public boolean onUnbind(Intent intent) {
close();
return super.onUnbind(intent);
}
private void close() {
if (bluetoothGatt == null) {
return;
}
bluetoothGatt.close();
bluetoothGatt = null;
}
public boolean connect() {
if (bluetoothAdapter == null || this.address == null || this.address.equals("")) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
try {
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
bluetoothGatt = device.connectGatt(MainActivity.this.getApplicationContext(), false, gattCallback);
Log.d(TAG,"GATT "+ bluetoothGatt);
return true;
} catch (IllegalArgumentException exception) {
Log.w(TAG, "Device not found with provided address.");
return false;
}
}
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
Log.i(TAG, intent + "");
MainActivity.this.getApplicationContext().sendBroadcast(intent);
}
private void broadcastUpdate(final String action, BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
public List<BluetoothGattService> getSupportedGattServices() {
if (bluetoothGatt == null) return null;
return bluetoothGatt.getServices();
}
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (bluetoothGatt == null) {
Log.w(TAG, "BluetoothGatt not initialized");
return;
}
bluetoothGatt.readCharacteristic(characteristic);
}
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,boolean enabled) {
if (bluetoothGatt == null) {
Log.w(TAG, "BluetoothGatt not initialized");
return;
}
bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
}
class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
}
}
private BluetoothLeService bluetoothLeService = new BluetoothLeService();
private final ServiceConnection serviceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (bluetoothLeService != null) {
if (!bluetoothAdapter.isEnabled()) {
Log.e(TAG, "Unable to initialize Bluetooth");
}
else{
bluetoothLeService.connect();
Log.i(TAG, "Service connected");
}
}
}
#Override
public void onServiceDisconnected(ComponentName name) {
bluetoothLeService = null;
}
};
private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.d(TAG, "RECEIVED " + action);
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
connected = true;
//Log.d(TAG, "CONNECTED");
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
connected = false;
//Log.d(TAG, "DISCONNECTED");
}
}
};
private final ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
#Override
public void onActivityResult(ActivityResult result) {
Log.i("RESULT", result.getResultCode() + "");
setup();
}
});
private void setup() {
bluetoothLeService.ctx = this.getApplicationContext();
Log.d("APPLICATIONCONTEXT", bluetoothLeService.ctx + "");
mDiscoverButton.setOnClickListener(this);
mAdvertiseButton.setOnClickListener(this);
mSendButton.setOnClickListener(this);
mBluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
if (!BluetoothAdapter.getDefaultAdapter().isMultipleAdvertisementSupported()) {
Toast.makeText(this, "Multiple advertisement not supported", Toast.LENGTH_SHORT).show();
mAdvertiseButton.setEnabled(false);
mDiscoverButton.setEnabled(false);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull #org.jetbrains.annotations.NotNull String[] permissions, #NonNull #org.jetbrains.annotations.NotNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 2) {
final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
if(!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
Intent enableLocationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
someActivityResultLauncher.launch(enableLocationIntent);
}
else{
setup();
}
}
}
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = (TextView) findViewById( R.id.text );
mDiscoverButton = (Button) findViewById( R.id.discover_btn );
mAdvertiseButton = (Button) findViewById( R.id.advertise_btn );
mSendButton = (Button) findViewById( R.id.send_btn );
this.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 2);
}
#Override
protected void onResume() {
super.onResume();
MainActivity.this.getApplicationContext().registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter());
}
#Override
protected void onPause() {
super.onPause();
MainActivity.this.getApplicationContext().unregisterReceiver(gattUpdateReceiver);
}
#Override
public void onClick(View v) {
Log.d(TAG, getString( R.string.ble_uuid ));
if( v.getId() == R.id.discover_btn ) {
discover();
} else if( v.getId() == R.id.advertise_btn ) {
advertise();
//MainActivity.this.getApplicationContext().registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter());
} else if (v.getId() == R.id.send_btn){
//MainActivity.this.getApplicationContext().unregisterReceiver(gattUpdateReceiver);
send();
}
}
public void advertise(){
BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
AdvertiseSettings settings = new AdvertiseSettings.Builder().setTimeout(0)
.setAdvertiseMode( AdvertiseSettings.ADVERTISE_MODE_BALANCED )
.setTxPowerLevel( AdvertiseSettings.ADVERTISE_TX_POWER_HIGH )
.setConnectable( true )
.build();
ParcelUuid pUuid = ParcelUuid.fromString( getString( R.string.ble_uuid ) ) ;
AdvertiseData data = new AdvertiseData.Builder()
.addServiceUuid( pUuid ).setIncludeDeviceName(false)
.build();
AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
Log.d(TAG, "START ADVERTISING");
super.onStartSuccess(settingsInEffect);
}
#Override
public void onStartFailure(int errorCode) {
Log.e( TAG, "Advertising onStartFailure: " + errorCode );
super.onStartFailure(errorCode);
}
};
advertiser.startAdvertising( settings, data, advertisingCallback );
}
public void discover(){
ScanFilter filter = new ScanFilter.Builder()
.setServiceUuid( ParcelUuid.fromString( getString(R.string.ble_uuid ) ) )
.build();
List<ScanFilter> filters = new ArrayList<>();
filters.add( filter );
ScanSettings settings = new ScanSettings.Builder()
.setScanMode( ScanSettings.SCAN_MODE_BALANCED )
.build();
mBluetoothLeScanner.startScan(filters, settings, mScanCallback);
Log.d(TAG, "Discovery started");
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
Log.d(TAG, "Discovery stopped");
mBluetoothLeScanner.stopScan(mScanCallback);
}
}, 10000);
}
public void send(){
Log.d(TAG, "START CONNECTIONG GATT");
mBluetoothLeScanner.stopScan(mScanCallback);
//boundGatt();
connectGatt();
}
public void boundGatt(){
Intent gattServiceIntent = new Intent(MainActivity.this.getApplicationContext(), BluetoothLeService.class);
bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
public void connectGatt(){
bluetoothLeService.connect();
}
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
return intentFilter;
}
}
Your Peripheral (phone A) does only advertisement, but BluetoothGattServer is not set up. That could be a reason of the described behavior - advertisement & scanning work, but connection doesn't.
BluetoothGatt + BluetoothGattCallback are for Central role (you call it phone B).
BluetoothGattServer + BluetoothGattServerCallback are for Peripheral (phone A).
Notes:
Connection from Central side (phone B) looks good, because when advertised device found, you get it using bluetoothAdapter.getRemoteDevice(address), then you call device.connectGatt
To transfer some data, you will need to add BluetoothGattService with BluetoothGattCharacteristic to your BluetoothGattServer - example of setup in Kotlin
Example project on github: BLEProof - it's in Kotlin, 2 apps communicate with each other: Central and Peripheral, all code in MainActivity.kt
in this code its works in the background but not working in the foreground I want to add a foreground service that implements Bluetooth connectivity and GATT connection as well. please help me in this code
in this code its works in the background but not working in the foreground I want to add a foreground service that implements Bluetooth connectivity and GATT connection as well. please help me in this code
in this code its works in the background but not working in the foreground I want to add a foreground service that implements Bluetooth connectivity and GATT connection as well. please help me in this code
public static BluetoothGattCharacteristic colorCharacteristic;
private HashMap<String, BluetoothGatt> gattHash = new HashMap<String, BluetoothGatt>();
private BluetoothManager bluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mGatt;
private boolean isConnected;
#Override
public IBinder onBind(Intent intent) {
initAdapter();
return kBinder;
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
private String address;
public void initBluetoothDevice(final String address, final Context context) {
this.address = address;
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if(isConnected())return;
if(null!=mGatt){
refreshDeviceCache(mGatt);
mGatt=null;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mGatt = device.connectGatt(context, false, bleGattCallback,BluetoothDevice.TRANSPORT_LE);
} else {
mGatt = device.connectGatt(context, false, bleGattCallback);
}
if (mGatt == null) {
System.out.println(device.getAddress() + "gatt is null");
}
// this.mContext=context;
// reconnect(true);
}
public String getDeviceAddress() {
return this.address;
}
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi,
final byte[] scanRecord) {
if (device.getAddress().equals(address) && Math.abs(rssi) < 90) {
});
}
}
};
private void initAdapter() {
if (bluetoothManager == null) {
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null) {
return;
}
}
mBluetoothAdapter = bluetoothManager.getAdapter();
}
public void disconnect() {
NeedReconnect = false;
if (mGatt == null)
return;
mGatt.disconnect();
}
public void disconnect(String address) {
ArrayList<BluetoothGatt> gatts = new ArrayList<BluetoothGatt>();
for (BluetoothGatt gatt : arrayGatts) {
if (gatt != null && gatt.getDevice().getAddress().equals(address)) {
gatts.add(gatt);
// gatt.disconnect();
gatt.close();
// gatt = null;
}
}
arrayGatts.removeAll(gatts);
}
public class LocalBinder extends Binder {
public BleService getService() {
return BleService.this;
}
}
private int discoverCount;
private Object ob = new Object();
private BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
String action = null;
Log.i(TAG, "onConnectionStateChange: status"+ status+" newstate "+newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
if (status == 133) {
mGatt.close();
mGatt = null;
return;
}
action = ACTION_GATT_CONNECTED;
try {
gatt.discoverServices();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
isConnected=false;
Log.i(TAG, "onConnectionStateChange: "+ACTION_GATT_DISCONNECTED);
if (mGatt != null) {
mGatt.close();
mGatt = null;
}
queues.clear();
if(!NeedReconnect) {
action = ACTION_GATT_DISCONNECTED;
broadcastUpdate(action);
}
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// if (mGatt == null)
// return;
if (status == BluetoothGatt.GATT_SUCCESS) {
String address = gatt.getDevice().getAddress();
String name = mBluetoothAdapter.getRemoteDevice(address)
.getName();
setCharacteristicNotification(true);
/* if (gatt != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
gatt.requestMtu(512);
}else{
setCharacteristicNotification(true);
}*/
discoverCount = 0;
} else {
// mGatt = null;
Log.w("servieDiscovered", "onServicesDiscovered received: "
+ status);
}
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
if (BluetoothGatt.GATT_SUCCESS == status) {
setCharacteristicNotification(true);
}else {
gatt.requestMtu(153);
}
}
public void onCharacteristicRead(BluetoothGatt gatt,
android.bluetooth.BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic, gatt
.getDevice().getAddress());
} else {
}
}
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor descriptor, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//MyLog.i("onDescriptorWrite");
// NeedReconnect = true;
isConnected=true;
// SharePreferenceUtils.setSpString(SharePreferenceUtils.KEY_ADDRESS,gatt.getDevice().getAddress());
broadcastUpdate(ACTION_GATT_onDescriptorWrite);
}else{
Log.i(TAG, "onDescriptorWrite: failed");
}
}
;
public void onCharacteristicChanged(BluetoothGatt gatt,
android.bluetooth.BluetoothGattCharacteristic characteristic) {
if (mGatt == null)
return;
Log.i(TAG, "onCharacteristicChanged: " + ResolveData.byte2Hex(characteristic.getValue()));
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic, gatt
.getDevice().getAddress());
// SendData.sendBus(ACTION_DATA_AVAILABLE, characteristic.getValue());
}
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
nextQueue();
} else {
// MyLog.i("status" + status);
}
}
;
};
public boolean refreshDeviceCache(BluetoothGatt gatt) {
try {
BluetoothGatt localBluetoothGatt = gatt;
Method localMethod = localBluetoothGatt.getClass().getMethod(
"refresh", new Class[0]);
if (localMethod != null) {
boolean bool = ((Boolean) localMethod.invoke(
localBluetoothGatt, new Object[0])).booleanValue();
return bool;
}
} catch (Exception localException) {
Log.e("s", "An exception occured while refreshing device");
}
return false;
}
private void broadcastUpdate(String action) {
BleData bleData = new BleData();
bleData.setAction(action);
RxBus.getInstance().post(bleData);
//Intent intent = new Intent(action);
//sendBroadcast(intent);
}
private void broadcast update(String action,
BluetoothGattCharacteristic characteristic, String mac) {
// Intent intent = new Intent(action);
byte[] data = characteristic.getValue();
BleData bleData = new BleData();
bleData.setAction(action);
bleData.setValue(data);
RxBus.getInstance().post(bleData);
}
public void readValue(BluetoothGattCharacteristic characteristic) {
if (mGatt == null) return;
mGatt.readCharacteristic(characteristic);
}
public void writeValue(byte[] value) {
if (mGatt == null||value==null) return;
BluetoothGattService service = mGatt.getService(SERVICE_DATA);
if (service == null) return;
BluetoothGattCharacteristic characteristic = service.getCharacteristic(DATA_Characteristic);
if (characteristic == null) return;
if (value[0] ==(byte) 0x47) {
NeedReconnect = false;
}
characteristic.setValue(value);
Log.i(TAG, "writeValue: "+ ResolveData.byte2Hex(value));
mGatt.writeCharacteristic(characteristic);
}
public void setCharacteristicNotification(boolean enable) {
// TODO Auto-generated method stub
if (mGatt == null) return;
BluetoothGattService service = mGatt.getService(SERVICE_DATA);
if (service == null) return;
BluetoothGattCharacteristic characteristic = service.getCharacteristic(NOTIY_Characteristic);
if (characteristic == null) return;
mGatt.setCharacteristicNotification(characteristic, enable);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(NOTIY);
if (descriptor == null) {
//MyLog.e("setCharacteristicNotification descriptor=null,所以不能发送使能数据");
return;
}
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
if (mGatt == null)
return;
mGatt.writeDescriptor(descriptor);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//MyLog.i("servicer destory");
}
Queue<byte[]> queues=new LinkedList<>();
public void offerValue(byte[]value) {
queues.offer(value);
}
public void nextQueue(){
final Queue<byte[]> requests=queues;
byte[]data=requests!=null?requests.poll():null;
writeValue(data);
}
public boolean isConnected(){
return this.isConnected;
}
}
I'd like to connect the Android application and sensors with bluetooth and display sensor data on the application, but I do not know where to change.
Is the data of the sensor stored in the character stick?
If so, how do you display the stored data?
The equipment you are using is the SONY MESH button.
Android ver 5.0.2
Android Studio ver 2.3.1
MainActivity.java
private final static int SDKVER_LOLLIPOP = 21;
private final static int MESSAGE_NEW_RECEIVEDNUM = 0;
private final static int MESSAGE_NEW_SENDNUM = 1;
private final static int REQUEST_ENABLE_BT = 123456;
private BluetoothManager mBleManager;
private BluetoothAdapter mBleAdapter;
private boolean mIsBluetoothEnable = false;
private BluetoothLeScanner mBleScanner;
private BluetoothGatt mBleGatt;
private BluetoothGattCharacteristic mBleCharacteristic;
private TextView mTxtReceivedNum;
private TextView mTxtSendNum;
private String meshdata = String.valueOf(0x00020103);
private String mStrReceivedNum = "";
private String mStrSendNum = "";
private static final String SERVICE_UUID = "72C90001-57A9-4D40-B746-534E22EC9F9E";
private static final String CHARACTERISTIC_UUID = "72C90003-57A9-4D40-B746-534E22EC9F9E";
private static final String CHARACTERISTIC_CONFIG_UUID = "00002902-0000-1000-8000-00805f9b34fb";
private Random mRandom = new Random();
private Timer mTimer;
private SendDataTimer mSendDataTimer;
private final LeScanCallback mScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mBleGatt = device.connectGatt(getApplicationContext(), false, mGattCallback);
}
});
}
};
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState)
{
if (newState == BluetoothProfile.STATE_CONNECTED) {
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mBleGatt != null)
{
mBleGatt.close();
mBleGatt = null;
}
mIsBluetoothEnable = false;
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
if (status == BluetoothGatt.GATT_SUCCESS) {
BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));
if (service != null)
{
mBleCharacteristic = service.getCharacteristic(UUID.fromString(CHARACTERISTIC_UUID));
if (mBleCharacteristic != null) {
mBleGatt = gatt;
boolean registered = mBleGatt.setCharacteristicNotification(mBleCharacteristic, true);
BluetoothGattDescriptor descriptor = mBleCharacteristic.getDescriptor(
UUID.fromString(CHARACTERISTIC_CONFIG_UUID));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBleGatt.writeDescriptor(descriptor);
mIsBluetoothEnable = true;
}
}
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
{
if (CHARACTERISTIC_UUID.equals(characteristic.getUuid().toString().toUpperCase()))
{
mStrReceivedNum = characteristic.getStringValue(0);
mBleHandler.sendEmptyMessage(MESSAGE_NEW_RECEIVEDNUM);
}
}
};
private Handler mBleHandler = new Handler()
{
public void handleMessage(Message msg)
{
switch (msg.what)
{
case MESSAGE_NEW_RECEIVEDNUM:
mTxtReceivedNum.setText(mStrReceivedNum);
break;
case MESSAGE_NEW_SENDNUM:
mTxtSendNum.setText(mStrSendNum);
break;
}
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIsBluetoothEnable = false;
mTxtReceivedNum = (TextView) findViewById(R.id.received_num);
mTxtSendNum = (TextView) findViewById(R.id.send_num);
mBleManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBleAdapter = mBleManager.getAdapter();
mTimer = new Timer();
mSendDataTimer = new SendDataTimer();
mTimer.schedule(mSendDataTimer, 500, 1000);
if ((mBleAdapter == null)
|| (! mBleAdapter.isEnabled())) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
else
{
this.scanNewDevice();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQUEST_ENABLE_BT:
if ((mBleAdapter != null)
|| (mBleAdapter.isEnabled())) {
this.scanNewDevice();
}
break;
}
}
private void scanNewDevice()
{
if (Build.VERSION.SDK_INT >= SDKVER_LOLLIPOP)
{
this.startScanByBleScanner();
}
else
{
mBleAdapter.startLeScan(mScanCallback);
}
}
#TargetApi(SDKVER_LOLLIPOP)
private void startScanByBleScanner()
{
mBleScanner = mBleAdapter.getBluetoothLeScanner();
mBleScanner.startScan(new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
result.getDevice().connectGatt(getApplicationContext(), false, mGattCallback);
}
#Override
public void onScanFailed(int intErrorCode)
{
super.onScanFailed(intErrorCode);
}
});
}
public class SendDataTimer extends TimerTask{
#Override
public void run() {
if(mIsBluetoothEnable)
{
mStrSendNum = String.valueOf(mRandom.nextInt(1000));
mBleHandler.sendEmptyMessage(MESSAGE_NEW_SENDNUM);
mBleCharacteristic.setValue(meshdata);
mBleGatt.writeCharacteristic(mBleCharacteristic);
}
}
}
#Override
protected void onDestroy()
{
mIsBluetoothEnable = false;
if(mBleGatt != null) {
mBleGatt.close();
mBleGatt = null;
}
super.onDestroy();
}
Related places
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic)
{
if (CHARACTERISTIC_UUID.equals(characteristic.getUuid().toString().toUpperCase()))
{
mStrReceivedNum = characteristic.getStringValue(0);
mBleHandler.sendEmptyMessage(MESSAGE_NEW_RECEIVEDNUM);
}
}
Related places
private Handler mBleHandler = new Handler()
{
public void handleMessage(Message msg)
{
switch (msg.what)
{
case MESSAGE_NEW_RECEIVEDNUM:
mTxtReceivedNum.setText(mStrReceivedNum);
break;
case MESSAGE_NEW_SENDNUM:
mTxtSendNum.setText(mStrSendNum);
break;
}
}
};
Related places
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIsBluetoothEnable = false;
mTxtReceivedNum = (TextView) findViewById(R.id.received_num);
mTxtSendNum = (TextView) findViewById(R.id.send_num);
Related places
public class SendDataTimer extends TimerTask{
#Override
public void run() {
if(mIsBluetoothEnable)
{
mStrSendNum = String.valueOf(mRandom.nextInt(1000));
mBleHandler.sendEmptyMessage(MESSAGE_NEW_SENDNUM);
mBleCharacteristic.setValue(mStrSendNum);
mBleGatt.writeCharacteristic(mBleCharacteristic);
}
}
}
activity_main.xml
<TextView
android:id="#+id/received_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:gravity="right"
/>
<TextView
android:id="#+id/send_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
/>
I am working on mediaplayer app, but i have problem with onDestroy methods, i need to continue with playing music when i minimalize the app. But when i do it stops playing and throws errors or when i comment it, it is playing in background but problem is that it doesnt stop even when i kill the app, i can controll it just with my notification controller, but when i destroy controller by swiping, it is playing and i have music in background without music player.
public class MainActivity extends AppCompatActivity {
private MediaPlayerService player;
private boolean serviceBound = false;
private ArrayList<Audio> audioList;
private RWAdapter rwa;
private RecyclerView rv;
public static final String Broadcast_PLAY_NEW_AUDIO = "com.example.rsabo.mp3player.PlayNewAudio";
public static final String Broadcast_PAUSE_AUDIO= "com.example.rsabo.mp3player.PauseAudio";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
loadAudio();
initRW();
}
private void initRW(){
if (audioList.size()>0) {
rv = (RecyclerView) findViewById(R.id.myRecyclerView);
rv.setLayoutManager(new LinearLayoutManager(this));
;
rwa = new RWAdapter(audioList, getApplicationContext());
rv.setAdapter(rwa);
rv.addOnItemTouchListener(new MyTouchListener(this, new onItemClickListener() {
#Override
public void onClick(View view, int index) {
playAudio(index);
}
}));
}
}
//ulozi sa instancia
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean("ServiceState", serviceBound);
}
//obnovi sa instancia tam kde bola naposledy ulozena
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
serviceBound = savedInstanceState.getBoolean("ServiceState");
}
//znici instanciu
#Override
protected void onDestroy() {
super.onDestroy();
// if(serviceBound){
// unbindService(serviceConnection);
// player.stopSelf();
// }
}
//viaze tuto triedu s prehravacom, nastavi hodnotu serviceBound na true ked sa vytvori spojenie
private ServiceConnection serviceConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MediaPlayerService.LocalBinder binder = (MediaPlayerService.LocalBinder) service;
player = binder.getService();
serviceBound = true;
Toast.makeText(MainActivity.this, "Service bound", Toast.LENGTH_SHORT).show();
}
#Override
public void onServiceDisconnected(ComponentName name) {
serviceBound = false;
}
};
//Metoda pozrie ci je sluzba aktivna,
//ak nie je, do uloziska hodi arraylist s pesnickami, a spusti sluzbu
//ak je vlozi do uloziska novy audioIndex a posle spravu ze ma spustit pesnicku
private void playAudio(int audioIndex){
if(!serviceBound){
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudio(audioList);
ulozisko.storeAudioIndex(audioIndex);
Intent playerIntent = new Intent(this, MediaPlayerService.class);
startService(playerIntent);
bindService(playerIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} else {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
ulozisko.storeAudioIndex(audioIndex);
Intent broadcastIntent = new Intent(Broadcast_PLAY_NEW_AUDIO);
sendBroadcast(broadcastIntent);
}
}
private void pauseAudio(){
Intent broadcastIntent = new Intent(Broadcast_PAUSE_AUDIO);
sendBroadcast(broadcastIntent);
}
//nacita pesnicky z mobilu
private void loadAudio() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
Cursor cursor = contentResolver.query(uri, null, selection, null, sortOrder);
if(cursor != null && cursor.getCount() > 0) {
audioList = new ArrayList<>();
while (cursor.moveToNext()){
String data = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));
String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));
audioList.add(new Audio(data, title, album, artist));
}
}
cursor.close();
}
}
MediaPlayerService
public class MediaPlayerService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnInfoListener, MediaPlayer.OnBufferingUpdateListener,
AudioManager.OnAudioFocusChangeListener {
private static final int NOTIFICATION_ID = 101;
private MediaSessionManager mediaSessionManager;
private MediaSessionCompat mediaSession;
private MediaControllerCompat.TransportControls transportControls;
private MediaPlayer mediaPlayer;
private String mediaFile;
private int resumePosition;
private AudioManager audioManager;
private boolean hovor = false;
private PhoneStateListener phoneStateListener;
private TelephonyManager telephonyManager;
private ArrayList<Audio> audioList;
private int audioIndex = -1;
private Audio activeAudio;
private final IBinder iBinder = new LocalBinder();
private PlayStatus status;
public static final String ACTION_PLAY = "com.example.rsabo.mp3player.ACTION_PLAY";
public static final String ACTION_PAUSE = "com.example.rsabo.mp3player.ACTION_PAUSE";
public static final String ACTION_PREVIOUS = "com.example.rsabo.mp3player.ACTION_PREVIOUS";
public static final String ACTION_NEXT = "com.example.rsabo.mp3player.ACTION_NEXT";
public static final String ACTION_STOP = "com.example.rsabo.mp3player.ACTION_STOP";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return iBinder;
}
//pri vytvoreni zavola metody callStateListener(),registerJeNahlasReciever(), registerPlayNewAudio()
#Override
public void onCreate() {
super.onCreate();
callStateListener();
registerJeNahlasReciever();
registerPlayNewAudio();
}
//podla priority zvuku v systeme zvysi zvuk, ukonci, zastavi alebo stisi mediaPlayer
#Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
if (mediaPlayer == null) initMediaPlayer();
else if (!mediaPlayer.isPlaying()) mediaPlayer.start();
mediaPlayer.setVolume(1.0f, 1.0f);
break;
case AudioManager.AUDIOFOCUS_LOSS:
if (mediaPlayer.isPlaying()) mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
if (mediaPlayer.isPlaying()) mediaPlayer.pause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mediaPlayer.isPlaying()) mediaPlayer.setVolume(0.1f, 0.1f);
break;
}
}
//metoda na ziskanie AudioFocusu/priority hrania zvuku
private boolean requestAudioFocus() {
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
//metoda ktora odstrani audioFocus
private boolean removeAudioFocus() {
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED == audioManager.abandonAudioFocus(this);
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
}
#Override
public void onCompletion(MediaPlayer mp) {
skipToNext();
buildNotification(PlayStatus.PLAYING);
}
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK:
Log.d("Media Player error", "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK" + extra);
break;
case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
Log.d("Media Player error", "MEDIA_ERROR_SERVER_DIED" + extra);
break;
case MediaPlayer.MEDIA_ERROR_UNKNOWN:
Log.d("Media Player error", "MEDIA_ERROR_UNKNOWN" + extra);
break;
}
return false;
}
#Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
#Override
public void onSeekComplete(MediaPlayer mp) {
}
class LocalBinder extends Binder {
MediaPlayerService getService() {
return MediaPlayerService.this;
}
}
//inicializacia mediaPlayeru, ak sa nenastavi cesta vyhodi chybu a zastavi sa
private void initMediaPlayer() {
if (mediaPlayer == null)
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnInfoListener(this);
mediaPlayer.reset();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
// nastavi cestu k hudbe
mediaPlayer.setDataSource(activeAudio.getData());
} catch (IOException e) {
e.printStackTrace();
stopSelf();
}
mediaPlayer.prepareAsync();
}
//nastavenie funkcie tlacidla play
private void playMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
//nastavenie funkcie tlacidla stop
private void stopMedia() {
if (mediaPlayer == null) return;
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
//nastavenie funkcie tlacidla pause
private void pauseMedia() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
resumePosition = mediaPlayer.getCurrentPosition();
}
}
//nastavenie funkcie tlacidla resume
private void resumeMedia() {
if (!mediaPlayer.isPlaying()) {
mediaPlayer.seekTo(resumePosition);
mediaPlayer.start();
}
}
//inicializuje prhravac, ak neziska audiofocus alebo cestu k hudbe zastavi sa
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
Ulozisko ulozisko = new Ulozisko(getApplicationContext());
audioList = ulozisko.loadAudio();
audioIndex = ulozisko.loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
} catch (NullPointerException e) {
stopSelf();
}
if (!requestAudioFocus()) {
stopSelf();
}
if (mediaSessionManager == null) {
try {
initMediaSession();
initMediaPlayer();
} catch (RemoteException e) {
e.printStackTrace();
stopSelf();
}
buildNotification(PlayStatus.PLAYING);
}
handleIncomingActions(intent);
return super.onStartCommand(intent, flags, startId);
}
//metode prida zrusenie audiofocusu a nastavi prehravac na null, vypne phoneStateListener, odregistruje recievre, zmaze notifikaciu a vycisti playlist
#Override
public void onDestroy() {
super.onDestroy();
if (mediaPlayer != null) {
stopMedia();
mediaPlayer.release();
}
removeAudioFocus();
if (phoneStateListener != null) {
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}
removeNotification();
unregisterReceiver(jeNahlasReciever);
unregisterReceiver(playNewAudio);
new Ulozisko(getApplicationContext()).clearCacheAudioPlaylist();
}
//ked sa vyberu sluchadla tak sa hranie zastavi
private BroadcastReceiver jeNahlasReciever = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
};
private void registerJeNahlasReciever() {
IntentFilter intentFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
registerReceiver(jeNahlasReciever, intentFilter);
}
//metoda ktora zisiti v akom stave je hovor, a ked telefon zvoni alebo prebieha hovor, zastavi prehravanie
private void callStateListener() {
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
case TelephonyManager.CALL_STATE_RINGING:
if (mediaPlayer != null) {
pauseMedia();
hovor = true;
}
break;
case TelephonyManager.CALL_STATE_IDLE:
if (mediaPlayer != null) {
if (hovor) {
hovor = false;
resumeMedia();
}
}
break;
}
}
};
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
//ked prepnem pesnicku tak sa pomocou tejto metody resetne prehravac a prepne na dalsiu pesnicku podla indexu ktory dostala v sprave
private BroadcastReceiver playNewAudio = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// if(status == PlayStatus.PAUSED) {
audioIndex = new Ulozisko(getApplicationContext()).loadAudioIndex();
if (audioIndex != -1 && audioIndex < audioList.size()) {
activeAudio = audioList.get(audioIndex);
} else {
stopSelf();
}
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
updateInfo();
buildNotification(PlayStatus.PLAYING);
// } else if (status == PlayStatus.PLAYING){
// pauseMedia();
// updateInfo();
// buildNotification(PlayStatus.PAUSED);
// }
}
};
private void registerPlayNewAudio() {
IntentFilter filter = new IntentFilter(MainActivity.Broadcast_PLAY_NEW_AUDIO);
registerReceiver(playNewAudio, filter);
}
//skontroluje ci mediaSessionManager existuje
//vytvori mediaSession a da mu controller
private void initMediaSession() throws RemoteException {
if (mediaSessionManager != null) return;
mediaSessionManager = (MediaSessionManager) getSystemService(Context.MEDIA_SESSION_SERVICE);
mediaSession = new MediaSessionCompat(getApplicationContext(), "Prehravac");
transportControls = mediaSession.getController().getTransportControls();
mediaSession.setActive(true);
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
updateInfo();
mediaSession.setCallback(new MediaSessionCompat.Callback() {
#Override
public void onPlay() {
super.onPlay();
resumeMedia();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onPause() {
super.onPause();
pauseMedia();
buildNotification(PlayStatus.PAUSED);
}
#Override
public void onSkipToNext() {
super.onSkipToNext();
skipToNext();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onSkipToPrevious() {
super.onSkipToPrevious();
skipToPrevious();
updateInfo();
buildNotification(PlayStatus.PLAYING);
}
#Override
public void onStop() {
super.onStop();
removeNotification();
stopSelf();
}
#Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
}
});
}
//updatne aktualne info o pesnicke
private void updateInfo() {
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
mediaSession.setMetadata(new MediaMetadataCompat.Builder()
//.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, activeAudio.getArtist())
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, activeAudio.getAlbum())
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, activeAudio.getTitle())
.build());
}
//metoda ktora prepne pesnicku na dalsiu, ak je pesnicka posledna tak ju nastavi na prvu v zozname
private void skipToNext() {
if (audioIndex == audioList.size() - 1) {
audioIndex = 0;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(++audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora prepne pesnicku dozadu, ak je na zaciatku zoznamu tak ju nastavi na poslednu
private void skipToPrevious() {
if (audioIndex == 0) {
audioIndex = audioList.size() - 1;
activeAudio = audioList.get(audioIndex);
} else {
activeAudio = audioList.get(--audioIndex);
}
new Ulozisko(getApplicationContext()).storeAudioIndex(audioIndex);
stopMedia();
mediaPlayer.reset();
initMediaPlayer();
}
//metoda ktora spravi v notifikacnom panely prehravac a vzdy ked sa vola tato metoda tak sa v notifikacii updatne info o pesnicke
private void buildNotification(PlayStatus playStatus) {
int notificationAction = android.R.drawable.ic_media_pause;
PendingIntent playAleboPause = null;
if (playStatus == PlayStatus.PLAYING) {
notificationAction = android.R.drawable.ic_media_pause;
playAleboPause = playbackAction(1);
status = PlayStatus.PLAYING;
} else if (playStatus == PlayStatus.PAUSED) {
notificationAction = android.R.drawable.ic_media_play;
playAleboPause = playbackAction(0);
status = PlayStatus.PAUSED;
}
Bitmap albumArt = BitmapFactory.decodeResource(getResources(), R.drawable.image);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(this)
.setShowWhen(false)
.setStyle(new NotificationCompat.MediaStyle()
.setMediaSession(mediaSession.getSessionToken())
.setShowActionsInCompactView(0, 1, 2))
.setColor(getResources().getColor(R.color.colorPrimary))
//.setLargeIcon(activeAudio.)
.setSmallIcon(android.R.drawable.stat_sys_headset)
.setContentText(activeAudio.getArtist())
.setContentTitle(activeAudio.getTitle())
.setSubText(activeAudio.getAlbum())
.addAction(android.R.drawable.ic_media_previous, "previous", playbackAction(3))
.addAction(notificationAction, "pause", playAleboPause)
.addAction(ic_media_next, "next", playbackAction(2));
((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(NOTIFICATION_ID, notificationBuilder.build());
}
//zmaze notifikaciu
private void removeNotification() {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
}
// nastavenie akcie na tlacidla v notifikacii
private PendingIntent playbackAction(int cisloAkcie) {
Intent akcia = new Intent(this, MediaPlayerService.class);
switch (cisloAkcie) {
case 0:
akcia.setAction(ACTION_PLAY);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 1:
akcia.setAction(ACTION_PAUSE);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 2:
akcia.setAction(ACTION_NEXT);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
case 3:
akcia.setAction(ACTION_PREVIOUS);
return PendingIntent.getService(this, cisloAkcie, akcia, 0);
default:
break;
}
return null;
}
//metoda zisti ktora akcia je aktualna a zavola metodu cez transportControls
private void handleIncomingActions(Intent playbackAction) {
if (playbackAction == null || playbackAction.getAction() == null) return;
String akcia = playbackAction.getAction();
if (akcia.equalsIgnoreCase(ACTION_PLAY)) {
transportControls.play();
} else if (akcia.equalsIgnoreCase(ACTION_PAUSE)) {
transportControls.pause();
} else if (akcia.equalsIgnoreCase(ACTION_NEXT)) {
transportControls.skipToNext();
} else if (akcia.equalsIgnoreCase(ACTION_PREVIOUS)) {
transportControls.skipToPrevious();
} else if (akcia.equalsIgnoreCase(ACTION_STOP)) {
transportControls.stop();
}
}
}
Try this to startForeground()
Notification.Builder mBuilder = new Notification.Builder(this)
.setSmallIcon(R.mipmap.ic_icon)
.setContentTitle(getString(R.string.title))
.setContentText("");
Intent resultIntent = new Intent(this, ResultIntent.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(ParentStack.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int mId = 1489;
startForeground(mId, mBuilder.build());
I am developing a code for heart rate detection using BLE. I am able to connect to the gatt server, and even broadcast updates. But I can't seem to detect any heart rate. Am I missing something?
Here'y my codes.
public class BleActivity extends Activity {
public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA";
private BluetoothDevicesAdapter bluetoothDevicesAdapter;
private BluetoothAdapter mBluetoothAdapter;
private Handler mHandler = new Handler();
private static final long SCAN_PERIOD = 5000;
private ProgressDialog progressDialog;
private BluetoothGatt mGatt;
#Bind(R.id.bleDeviceListView)
ListView listView;
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ble);
ButterKnife.bind(this);
bluetoothDevicesAdapter = new BluetoothDevicesAdapter(getApplicationContext());
listView.setAdapter(bluetoothDevicesAdapter);
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
#OnClick(R.id.scanButton)
public void onScanClicked() {
scanLeDevice();
}
#OnItemClick(R.id.bleDeviceListView)
public void onItemClicked(int position) {
connectToDevice((BluetoothDevice) bluetoothDevicesAdapter.getItem(position));
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
//CONFIRMS IF BLUETOOTH IS ENABLED
if (!mBluetoothAdapter.isEnabled()) {
if (!mBluetoothAdapter.isEnabled()) {
GenericDialogBox.EnableBluetoothBox(BleActivity.this, "Notice", "This app requires bluetooth. Enable?", mBluetoothAdapter);
}
}
}
private void scanLeDevice() {
bluetoothDevicesAdapter.clear();
bluetoothDevicesAdapter.notifyDataSetChanged();
progressDialog = new ProgressDialog(BleActivity.this);
progressDialog.setCancelable(false);
progressDialog.setMessage("Scanning Devices");
progressDialog.show();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
mBluetoothAdapter.stopLeScan(leScanCallback);
progressDialog.hide();
mBluetoothAdapter.stopLeScan(leScanCallback);
progressDialog.dismiss();
progressDialog = null;
}
}, SCAN_PERIOD);
mBluetoothAdapter.startLeScan(leScanCallback);
}
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
runOnUiThread(new Runnable() {
#Override
public void run() {
bluetoothDevicesAdapter.addDevice(device);
bluetoothDevicesAdapter.notifyDataSetChanged();
}
});
}
};
public void connectToDevice(BluetoothDevice device) {
if (mGatt == null) {
mGatt = device.connectGatt(this, false, btleGattCallback);
progressDialog = new ProgressDialog(BleActivity.this);
progressDialog.setMessage("Connecting to Gatt Server.");
progressDialog.setCancelable(false);
progressDialog.show();
}
}
private final BluetoothGattCallback btleGattCallback = new BluetoothGattCallback() {
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
String intentAction;
Log.e("onConnectionStateChange", "Status: " + status);
switch (newState) {
case BluetoothProfile.STATE_CONNECTED:
intentAction = ACTION_GATT_CONNECTED;
Log.e("gattCallback", "STATE_CONNECTED");
progressDialog.dismiss();
progressDialog = null;
broadcastUpdate(intentAction);
mGatt.discoverServices();
break;
case BluetoothProfile.STATE_DISCONNECTED:
intentAction = ACTION_GATT_DISCONNECTED;
Log.e("gattCallback", "STATE_DISCONNECTED");
BluetoothDevice mDevice = gatt.getDevice();
mGatt = null;
broadcastUpdate(intentAction);
break;
default:
Log.e("gattCallback", "STATE_OTHER");
}
}
#Override
public void onServicesDiscovered(final BluetoothGatt gatt, final int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
List<BluetoothGattService> services = gatt.getServices();
BluetoothGattCharacteristic therm_char;
for (int i = 0; i < services.size(); i++) {
therm_char = services.get(i).getCharacteristics().get(0);
if(therm_char.getUuid().equals(SampleGattAttributes.HEART_RATE_MEASUREMENT)){
gatt.setCharacteristicNotification(therm_char, true);
BluetoothGattDescriptor descriptor = therm_char.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mGatt.writeDescriptor(descriptor);
}
}
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
Log.e("gattCallback", "Service discovered" + gatt.getServices() + " Status: " + status);
} else {
Log.e("BluetoothServices: ", "onServicesDiscovered received: " + status);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
};
private void broadcastUpdate(final String action) {
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
private void broadcastUpdate(final String action,
final BluetoothGattCharacteristic characteristic) {
final Intent intent = new Intent(action);
// This is special handling for the Heart Rate Measurement profile. Data
// parsing is carried out as per profile specifications.
if (UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT).equals(characteristic.getUuid())) {
int flag = characteristic.getProperties();
int format = -1;
if ((flag & 0x01) != 0) {
format = BluetoothGattCharacteristic.FORMAT_UINT16;
Log.d("Bluetooth Service: ", "Heart rate format UINT16.");
} else {
format = BluetoothGattCharacteristic.FORMAT_UINT8;
Log.d("Bluetooth Service: ", "Heart rate format UINT8.");
}
final int heartRate = characteristic.getIntValue(format, 1);
Log.d("Bluetooth Service: ", String.format("Received heart rate: %d", heartRate));
intent.putExtra(EXTRA_DATA, String.valueOf(heartRate));
} else {
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
for(byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
intent.putExtra(EXTRA_DATA, new String(data) + "\n" +
stringBuilder.toString());
}
}
sendBroadcast(intent);
}
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (ACTION_GATT_CONNECTED.equals(action)) {
Toast.makeText(getApplicationContext(), "Connected to Service.", Toast.LENGTH_SHORT).show();
invalidateOptionsMenu();
} else if (ACTION_GATT_DISCONNECTED.equals(action)) {
Toast.makeText(getApplicationContext(), "Connected to Service.", Toast.LENGTH_SHORT).show();
} else if (ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
//Update Connection State
} else if (ACTION_DATA_AVAILABLE.equals(action)) {
Toast.makeText(getApplicationContext(), intent.getStringExtra(EXTRA_DATA), Toast.LENGTH_SHORT).show();
}
}
};
private static IntentFilter makeGattUpdateIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_GATT_CONNECTED);
intentFilter.addAction(ACTION_GATT_DISCONNECTED);
intentFilter.addAction(ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(ACTION_DATA_AVAILABLE);
return intentFilter;
}
And this is the sampleAttributes Class.
public class SampleGattAttributes {
private static HashMap<String, String> attributes = new HashMap();
public static String HEART_RATE_MEASUREMENT = "00002a37-0000-1000-8000-00805f9b34fb";
public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
static {
// Sample Services.
attributes.put("0000180d-0000-1000-8000-00805f9b34fb", "Heart Rate Service");
attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service");
// Sample Characteristics.
attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement");
attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String");
}
public static String lookup(String uuid, String defaultName) {
String name = attributes.get(uuid);
return name == null ? defaultName : name;
}
}
And also is there a way to log if the device is searching for any changes from time to time?
Thank you!