I am making a video call app. I want to make a reconnection scenario just like whatsapp i.e. if the user or remote user internet disconnects after waiting for 10-15 seconds call should end for both. here is my code:
private final IRtcEngineEventHandler mRtcEventHandler = new IRtcEngineEventHandler() {
#Override
public void onJoinChannelSuccess(String channel, final int uid, int elapsed) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (AppSharedPreferences.getUser(context).getUserTypeId() == 2) {
updateDoctorStatus("3");
}
Log.e("Agora", "Join channel success, uid: " + (uid & 0xFFFFFFFFL));
}
});
}
#Override
public void onFirstRemoteVideoDecoded(final int uid, int width, int height, int elapsed) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Agora", "First remote video decoded, uid: " + (uid & 0xFFFFFFFFL));
reconnectingView.setVisibility(View.GONE);
timerRunning = true;
appointmentStarted = true;
if (reconnecting) {
timeLeftInMillis = AppSharedPreferences.getCallTimer(VideoChatViewActivity.this);
countDownTimer.cancel();
}
callingView.setVisibility(View.GONE);
handler.removeCallbacks(runnableCode);
callHandler.removeCallbacks(runnableforCalling);
startMeeting();
updateAppointmentStatus();
setupRemoteVideo(uid);
}
});
}
#Override
public void onUserOffline(final int uid, final int reason) {
Log.e("Agora", "User offline, reason: " + reason);
ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo nInfo = cm.getActiveNetworkInfo();
boolean connected = nInfo != null && nInfo.isAvailable() && nInfo.isConnected();
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Agora", "User offline, uid: " + (uid & 0xFFFFFFFFL));
if (reason == 0) {
onRemoteUserLeft();
endCall();
} else {
timerRunning = false;
reconnecting = true;
reconnectingView.setVisibility(View.VISIBLE);
reconnectingText.setText("Reconnecting....");
Toast.makeText(VideoChatViewActivity.this, "Doctor internet disconnected", Toast.LENGTH_LONG).show();
reconnectingHandler.postDelayed(() -> {
if (reconnecting) {
onRemoteUserLeft();
endCall();
}
}, 10000);
}
}
});
}
#Override
public void onUserMuteVideo(final int uid, final boolean muted) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.e("Agora", "User Muted, uid: " + (uid & 0xFFFFFFFFL));
Log.e("Agora", "User Muted,: " + muted);
if (muted)
remote_off.setVisibility(View.VISIBLE);
else
remote_off.setVisibility(View.GONE);
}
});
}
#Override
public void onRejoinChannelSuccess(String channel, int uid, int elapsed) {
super.onRejoinChannelSuccess(channel, uid, elapsed);
reconnecting = false;
Toast.makeText(VideoChatViewActivity.this, "Reconnected", Toast.LENGTH_LONG).show();
}
#Override
public void onNetworkQuality(int uid, final int txQuality, final int rxQuality) {
runOnUiThread(() -> {
// Log.e("Quality", rxQuality + "");
if (rxQuality == Quality.VBAD) {
signals.setImageDrawable(getResources().getDrawable(R.drawable.signal1));
}
if (rxQuality == Quality.BAD) {
signals.setImageDrawable(getResources().getDrawable(R.drawable.signal2));
}
if (rxQuality == Quality.POOR) {
signals.setImageDrawable(getResources().getDrawable(R.drawable.signal3));
}
if (rxQuality == Quality.GOOD) {
signals.setImageDrawable(getResources().getDrawable(R.drawable.signal4));
}
if (rxQuality == Quality.EXCELLENT) {
signals.setImageDrawable(getResources().getDrawable(R.drawable.signal5));
}
});
}
#Override
public void onConnectionStateChanged(int state, int reason) {
Log.d(TAG, "Connection state changes to "
+ state + " reason: " + reason);
}
};
Any help will be appreciated. In the code above there is a problem, I have used a handler in onUserOffline method which will end call after 10 seconds of user offline, but if the user reconnects within 10 seconds the handler still works and the call ends after 10 seconds.
Instead of using handler, I'd prefer you to use CountDownTimer. In this, you can also stop it in the middle. You can refer the code below:
//In your class
CountDownTimer mCountDownTimer;
//when the network goes
mCountDownTimer = new CountDownTimer((10 * 1000), (1 * 1000)){ // multiple the number of seconds by thousand to get the appropriate results. Here 10 * 1000 = 10000(10 seconds) and 1 * 1000 = 1000(1 second)
#Override
public void onTick(long millisInFuture){}
#Override
public void onFinish(){
//10 seconds have finished. Drop the call.
}
}.start();
//If the internet comes back
if(mCountDownTimer != null)
mCountDownTimer.cancel();
I trying to connect two android device over the Gatt Protocol.
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattServer;
import android.bluetooth.BluetoothGattServerCallback;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.ParcelUuid;
import android.util.Log;
import java.util.HashSet;
import java.util.Set;
public class GattServer {
private final String TAG = GattServer.class.getSimpleName();
private Context applicationContext;
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private LocationManager locationManager;
BluetoothLeAdvertiser bluetoothLeAdvertiser;
private static GattServer gattServer;
private BluetoothGattServer bluetoothGattServer;
private Set<BluetoothDevice> connectedDevices = new HashSet<>();
public GattServer(Context applicationContext) {
this.applicationContext = applicationContext;
bluetoothManager = (BluetoothManager) applicationContext.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
locationManager = (LocationManager) applicationContext.getSystemService(Context.LOCATION_SERVICE);
registerBluetoothStateReceiver();
}
public static GattServer getInstance(Context context) {
if (gattServer == null) {
gattServer = new GattServer(context.getApplicationContext());
}
return gattServer;
}
private BroadcastReceiver bluetoothStateReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
switch (state) {
case BluetoothAdapter.STATE_ON:
println("Bluetooth adapter state is changed to ON");
break;
case BluetoothAdapter.STATE_OFF:
println("Bluetooth adapter state is changed to OF");
break;
default:
// Do nothing
}
}
};
private void println(String message) {
Log.e(TAG, message);
}
private void registerBluetoothStateReceiver() {
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
try {
applicationContext.registerReceiver(bluetoothStateReceiver, filter);
} catch (Exception e) {
e.printStackTrace();
}
}
private void unregisterBluetoothStateReceiver() {
try {
applicationContext.unregisterReceiver(bluetoothStateReceiver);
} catch (Exception e) {
e.printStackTrace();
}
}
public void destroy() {
stop();
unregisterBluetoothStateReceiver();
gattServer = null;
}
private AdvertiseCallback advertiseCallback = new AdvertiseCallback() {
#Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
super.onStartSuccess(settingsInEffect);
println("Advertise Started");
listener.onAdvertiseStarted();
}
#Override
public void onStartFailure(int errorCode) {
super.onStartFailure(errorCode);
println("Advertise Failed : " + errorCode);
listener.onAdvertiseFail(errorCode);
}
};
private void startAdvertising() {
bluetoothLeAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
if (bluetoothLeAdvertiser == null || !bluetoothAdapter.isMultipleAdvertisementSupported()) {
Log.e(TAG, "Failed to create advertiser");
listener.onAdvertiseFail(-1);
return;
}
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
.setConnectable(true)
.setTimeout(0)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.build();
AdvertiseData data = new AdvertiseData.Builder()
.setIncludeDeviceName(true)
.setIncludeTxPowerLevel(false)
.addServiceUuid(new ParcelUuid(GattServerConfiguration.SERVICE_UUID))
.build();
bluetoothLeAdvertiser.startAdvertising(settings, data, advertiseCallback);
}
private BluetoothGattServerCallback gattCallback = new BluetoothGattServerCallback() {
#Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
super.onConnectionStateChange(device, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
println("Device Connected : " + device.getAddress());
connectedDevices.add(device);
listener.onDeviceConnected(device);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
println("Device Disconnected : " + device.getAddress());
connectedDevices.remove(device);
listener.onDeviceDisconnected(device);
}
}
#Override
public void onServiceAdded(int status, BluetoothGattService service) {
super.onServiceAdded(status, service);
Log.d(TAG, "onServiceAdded() called with: status = [" + status + "], service = [" + service + "]");
listener.onServiceAdded();
}
#Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
Log.d(TAG, "onCharacteristicReadRequest() called with: device = [" + device + "], requestId = [" + requestId + "], offset = [" + offset + "], characteristic = [" + characteristic + "]");
listener.onReceive(device, characteristic);
}
#Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log.d(TAG, "onCharacteristicWriteRequest() called with: device = [" + device + "], requestId = [" + requestId + "], characteristic = [" + characteristic + "], preparedWrite = [" + preparedWrite + "], responseNeeded = [" + responseNeeded + "], offset = [" + offset + "], value = [" + value + "]");
}
#Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
super.onDescriptorReadRequest(device, requestId, offset, descriptor);
Log.d(TAG, "onDescriptorReadRequest() called with: device = [" + device + "], requestId = [" + requestId + "], offset = [" + offset + "], descriptor = [" + descriptor + "]");
if (GattServerConfiguration.CCC_DESCRIPTOR_UUID.equals(descriptor.getUuid())) {
Log.d(TAG, "Config descriptor read");
byte[] returnValue;
if (connectedDevices.contains(device)) {
returnValue = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
} else {
returnValue = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
}
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, returnValue);
} else {
Log.w(TAG, "Unknown descriptor read request");
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
}
}
#Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
Log.d(TAG, "onDescriptorWriteRequest() called with: device = [" + device + "], requestId = [" + requestId + "], descriptor = [" + descriptor + "], preparedWrite = [" + preparedWrite + "], responseNeeded = [" + responseNeeded + "], offset = [" + offset + "], value = [" + value + "]");
if (GattServerConfiguration.CCC_DESCRIPTOR_UUID.equals(descriptor.getUuid())) {
Log.d(TAG, "Config descriptor read");
byte[] returnValue;
if (connectedDevices.contains(device)) {
returnValue = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
} else {
returnValue = BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE;
}
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, 0, returnValue);
} else {
Log.w(TAG, "Unknown descriptor read request");
bluetoothGattServer.sendResponse(device, requestId, BluetoothGatt.GATT_FAILURE, 0, null);
}
}
#Override
public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
super.onExecuteWrite(device, requestId, execute);
Log.d(TAG, "onExecuteWrite() called with: device = [" + device + "], requestId = [" + requestId + "], execute = [" + execute + "]");
}
#Override
public void onNotificationSent(BluetoothDevice device, int status) {
super.onNotificationSent(device, status);
Log.d(TAG, "onNotificationSent() called with: device = [" + device + "], status = [" + status + "]");
}
#Override
public void onMtuChanged(BluetoothDevice device, int mtu) {
super.onMtuChanged(device, mtu);
Log.d(TAG, "onMtuChanged() called with: device = [" + device + "], mtu = [" + mtu + "]");
}
#Override
public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyUpdate(device, txPhy, rxPhy, status);
Log.d(TAG, "onPhyUpdate() called with: device = [" + device + "], txPhy = [" + txPhy + "], rxPhy = [" + rxPhy + "], status = [" + status + "]");
}
#Override
public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
super.onPhyRead(device, txPhy, rxPhy, status);
Log.d(TAG, "onPhyRead() called with: device = [" + device + "], txPhy = [" + txPhy + "], rxPhy = [" + rxPhy + "], status = [" + status + "]");
}
};
private void startServer() {
bluetoothGattServer = bluetoothManager.openGattServer(applicationContext, gattCallback);
if (bluetoothGattServer == null) {
println("Server is null");
return;
}
bluetoothGattServer.addService(GattServerConfiguration.createGattService());
}
public void launch() {
if (isReady()) {
startServer();
startAdvertising();
}
}
private void stopAdvertising() {
if (bluetoothLeAdvertiser == null) return;
bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
}
private void stopServer() {
if (bluetoothGattServer == null) return;
bluetoothGattServer.close();
}
public void stop() {
stopAdvertising();
stopServer();
connectedDevices.clear();
}
private boolean isReady() {
if (bluetoothManager == null) {
return false;
}
return bluetoothAdapter.isEnabled() && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
private IGattServer listener;
public void setCallback(IGattServer listener) {
this.listener = listener;
}
}
Above code, successfully starts advertisement,
Another device successfully receive device in LE Scan (Using UUID's filter)
But connectGatt() not providing any callback.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
bluetoothGatt = bluetoothDevice.connectGatt(
getApplicationContext(), true, gattCallback,
BluetoothDevice.TRANSPORT_LE
);
} else {
bluetoothGatt = bluetoothDevice.connectGatt(getApplicationContext(), true, gattCallback);
}
Gatt Callback Sample Code.
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
writeLog("onConnectionStateChange() called with: gatt = [" + gatt + "], status = [" + status + "], newState = [" + newState + "]");
broadcastUpdate(
ACTION_GATT_MESSAGE,
"onConnectionStateChange() called with: gatt = $gatt, status = $status, newState = $newState"
);
if (status == 8) {
writeLog("BLE Out Of Range");
broadcastUpdate(ACTION_GATT_MESSAGE, "BLE Out Of Range status == 8");
} else if (status == 19) {
writeLog("BLE Disconnected By Device");
broadcastUpdate(ACTION_GATT_MESSAGE, "BLE Disconnected By Device status == 19");
} else if (status == 22) {
writeLog("BLE Issue with bond");
broadcastUpdate(ACTION_GATT_MESSAGE, "BLE Issue with bond status == 22");
} else if (status == 133 || status == 62) {
writeLog("BLE Device not found");
broadcastUpdate(
ACTION_GATT_MESSAGE,
"BLE Device not found status == 133 || status == 62"
);
disconnect();
close();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
connectDevice(bluetoothAdapter.getRemoteDevice(PrefManager.getInstance(getApplicationContext()).getLeAddress()));
return;
}
if (newState == BluetoothProfile.STATE_CONNECTED) {
connected = true;
broadcastUpdate(ACTION_GATT_CONNECTED);
bluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
connected = false;
broadcastUpdate(ACTION_GATT_DISCONNECTED);
stopSelf();
}
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
writeLog("onServicesDiscovered() called with: gatt = [" + gatt + "], status = [" + status + "]");
if (status == BluetoothGatt.GATT_SUCCESS) {
Intent intent = new Intent(ACTION_GATT_SERVICES_DISCOVERED);
ArrayList<BluetoothGattService> services = new ArrayList<BluetoothGattService>();
for (BluetoothGattService gattService : gatt.getServices()) {
services.add(gattService);
}
intent.putParcelableArrayListExtra("services", services);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
broadcastUpdate(intent);
} else {
broadcastUpdate(ACTION_GATT_NO_SERVICES_DISCOVERED);
}
}
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.e(
TAG,
"onCharacteristicRead() called with: gatt = $gatt, characteristic = $characteristic, status = $status"
);
if (status == BluetoothGatt.GATT_SUCCESS) {
Intent intent = new Intent(ACTION_DATA_AVAILABLE);
intent.putExtra("bytes", characteristic.getValue());
//lintent.putExtra("data", characteristic.getValue().toString());
broadcastUpdate(intent);
}
}
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.e(
TAG,
"onCharacteristicWrite() called with: gatt = " + gatt + ", characteristic = " + characteristic + ", status = " + status
);
if (canceled || !connected || writeCharacteristic == null) {
writeLog("Return Form write 1");
return;
}
if (status != BluetoothGatt.GATT_SUCCESS) {
writeLog("Return Form write 2");
broadcastUpdate(ACTION_DATA_WRITE_FAIL);
return;
}
if (canceled) return;
writeLog("Write Success Checking for next bytes");
if (characteristic.getUuid().toString().equals(writeCharacteristic.getUuid().toString())) { // NOPMD - test object identity
writeNext();
}
}
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Log.e(
TAG,
"onCharacteristicChanged() called with: gatt = $gatt, characteristic = $characteristic"
);
if (characteristic.getUuid().toString().equals(readCharacteristic.getUuid().toString())) {
Intent intent = new Intent(ACTION_DATA_AVAILABLE);
intent.putExtra("bytes", characteristic.getValue());
broadcastUpdate(intent);
}
}
#Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
Log.e(
TAG,
"onDescriptorRead() called with: gatt = $gatt, descriptor = $descriptor, status = $status"
);
}
#Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
writeLog("onDescriptorWrite() called with: gatt = [" + gatt + "], descriptor = [" + descriptor + "], status = [" + status + "]");
}
#Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
writeLog("onReliableWriteCompleted() called with: gatt = [" + gatt + "], status = [" + status + "]");
}
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
writeLog("onReadRemoteRssi() called with: gatt = [" + gatt + "], rssi = [" + rssi + "], status = [" + status + "]");
}
#Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
payloadSize = mtu - 3;
writeLog("payload size $payloadSize");
}
enableTxNotification();
}
#Override
public void onServiceChanged(#NonNull BluetoothGatt gatt) {
super.onServiceChanged(gatt);
}
};
I solved connection issue by.
bluetoothGatt = bluetoothDevice.connectGatt(
getApplicationContext(), false, gattCallback,
BluetoothDevice.TRANSPORT_AUTO
);
I am working on my project trying to add a waypoint in between of the route that I generated from my Location to Destination, short (point A to point B). I am not able to do this due to only a singular marker added to the calculateDirections() method and calculated.
How program works:
Location is added to the map, the first point is added when the user searches for the location in an autocomplete view and it gets calculated straight away showing the route to the user. Once this is done, user is able to click anywhere on the map to add an additional marker.
The problem:
Once the additional marker is added, the program just reroutes everything to the new point leaving the initial point. What can I do to fix this issue, here is the essential code for autocomplete method, calculate route and calculate popylines:
mSearchText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
Intent intent = new
Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY,
fields)
.build(MapsActivity.this);
startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
hideSoftKeyboard();
return false;
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable
Intent data) {
if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Place place = Autocomplete.getPlaceFromIntent(data);
Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
String searchString = place.getName();
Geocoder geocoder = new Geocoder(MapsActivity.this,
Locale.getDefault());
List<Address> list;
try {
list = geocoder.getFromLocationName(searchString, 1);
if (list.size()> 0){
Address address = list.get(0);
LatLng latLng = new
LatLng(address.getLatitude(),address.getLongitude());
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng,15));
MarkerOptions marker = new
MarkerOptions().position(latLng);
calculateDirections(marker);
//add on map click listener and add an additional marker
mMap.setOnMapClickListener(new
GoogleMap.OnMapClickListener() {
public void onMapClick(LatLng latLng) {
List<LatLng> list = new ArrayList<>();
list.add(latLng);
// Add some markers to the map, and add a data
object to each marker
MarkerOptions marker2 = new
MarkerOptions().position(latLng);
calculateDirections(marker2);
}
});
}
} catch (IOException e) {
Log.e(TAG, "geoLocate: IOException: " + e.getMessage());
e.printStackTrace();
}
} else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
Status status = Autocomplete.getStatusFromIntent(data);
Log.i(TAG, status.getStatusMessage());
} else if (resultCode == RESULT_CANCELED) {
// The user canceled the operation.
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
private void calculateDirections(MarkerOptions marker){
Log.d(TAG, "calculateDirections: calculating directions.");
ArrayList<MarkerOptions> markers = new ArrayList<>(2);
markers.add(marker);
for (int i = 0; i < markers.size(); i++) {
dest1 = markers.get(0);
com.google.maps.model.LatLng destination = new
com.google.maps.model.LatLng(
dest1.getPosition().latitude,
dest1.getPosition().longitude
);
if (markers.size() > 1){
dest2 = markers.get(1);
DirectionsApiRequest directions = new
DirectionsApiRequest(mGeoApiContext);
directions.alternatives(true);
directions.origin(
new com.google.maps.model.LatLng(
userPosition.getPosition().latitude,
userPosition.getPosition().longitude
)
);
directions.optimizeWaypoints(true);
directions.waypoints(
new com.google.maps.model.LatLng(
dest2.getPosition().latitude,
dest2.getPosition().longitude
)
);
Log.d(TAG, "calculateDirections: destination: " +
destination.toString());
directions.destination(destination).setCallback(new
PendingResult.Callback<DirectionsResult>() {
#Override
public void onResult(DirectionsResult result) {
Log.d(TAG, "calculateDirections: routes: " +
result.routes[0].toString());
Log.d(TAG, "calculateDirections: duration: " +
result.routes[0].legs[0].duration);
Log.d(TAG, "calculateDirections: distance: " +
result.routes[0].legs[0].distance);
Log.d(TAG, "calculateDirections: geocodedWayPoints: "
+ result.geocodedWaypoints[0].toString());
addPolylinesToMap(result);
}
#Override
public void onFailure(Throwable e) {
Log.e(TAG, "calculateDirections: Failed to get
directions: " + e.getMessage());
}
});
}
else {
DirectionsApiRequest directions = new
DirectionsApiRequest(mGeoApiContext);
directions.alternatives(true);
directions.origin(
new com.google.maps.model.LatLng(
userPosition.getPosition().latitude,
userPosition.getPosition().longitude
)
);
Log.d(TAG, "calculateDirections: destination: " +
destination.toString());
directions.destination(destination).setCallback(new
PendingResult.Callback<DirectionsResult>() {
#Override
public void onResult(DirectionsResult result) {
Log.d(TAG, "calculateDirections: routes: " +
result.routes[0].toString());
Log.d(TAG, "calculateDirections: duration: " +
result.routes[0].legs[0].duration);
Log.d(TAG, "calculateDirections: distance: " +
result.routes[0].legs[0].distance);
Log.d(TAG, "calculateDirections: geocodedWayPoints: "
+ result.geocodedWaypoints[0].toString());
addPolylinesToMap(result);
}
#Override
public void onFailure(Throwable e) {
Log.e(TAG, "calculateDirections: Failed to get
directions: " + e.getMessage());
}
});
}
}
}
private void addPolylinesToMap(final DirectionsResult result){
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Log.d(TAG, "run: result routes: " + result.routes.length);
//check if there are any polylines selected and remove the old
one before the new
//one is selected
if(mPolylinesData.size() > 0){
for (PolylineData polylineData: mPolylinesData){
polylineData.getPolyline().remove();
}
mPolylinesData.clear();
mPolylinesData = new ArrayList<>();
}
double duration = 999999;
for(DirectionsRoute route: result.routes){
Log.d(TAG, "run: leg: " + route.legs[0].toString());
// Get all the lines on checklist by calling decoder path
List<com.google.maps.model.LatLng> decodedPath =
PolylineEncoding.decode(route.overviewPolyline.getEncodedPath());
// Adding new array list by adding all the lines
List<LatLng> newDecodedPath = new ArrayList<>();
// This loops through all the LatLng coordinates of ONE
polyline.
for(com.google.maps.model.LatLng latLng: decodedPath){
newDecodedPath.add(new LatLng(
latLng.lat,
latLng.lng
));
}
Polyline polyline = mMap.addPolyline(new
PolylineOptions().addAll(newDecodedPath));
polyline.setColor(ContextCompat.getColor(getApplicationContext(),
R.color.darkGrey));
polyline.setClickable(true);
mPolylinesData.add(new PolylineData(polyline,
route.legs[0]));
// Measure time in seconds of all trip durations and
select the shortest duration
double tempDuration = route.legs[0].duration.inSeconds;
if(tempDuration < duration){
duration = tempDuration;
onPolylineClick(polyline);
}
}
}
});
}
This might sound really basic but I'm a beginner at Android BLE Development.
So far I am able to Create my Nexus 9 device as a peripheral device and Moto G as Central. Plus i'm connecting the devices successfully. But i cant figure out that when i send a characteristic from central device where will it be received from peripheral? The Advertise call back only return if advertisement is started successfully of not(Which in my case is successful)
Here is my peripheral Code
btleGattCallback = new BluetoothGattCallback() {
#Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
// this will get called when a device connects or disconnects
}
#Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w("doscover", "onServicesDiscovered received: " + status);
}
}
};
BeaconParser bp = new BeaconParser().setBeaconLayout("m:2-3=0,i:4-19,p:20-20");
mBeaconTransmitter = new BeaconTransmitter(this, bp );
// Transmit a beacon with Identifiers 2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6 1 2
Long li = new Long(-0l);
ArrayList<Long> l = new ArrayList<Long>();
l.add(li);
Beacon beacon = new Beacon.Builder()
.setId1("2F234454-CF6D-4A0F-ADF2-F4911BA9FFA6")
.setId2("1")
.setId3("2")
.setManufacturer(0x00ff) // Choose a number of 0x00ff or less as some devices cannot detect beacons with a manufacturer code > 0x00ff
.setTxPower(-59)
.setDataFields(l)
.build();
mBeaconTransmitter.startAdvertising(beacon);
And the Central Code ofcorse
btManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE) ;
madapter = btManager.getAdapter();
if (madapter != null && !madapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,1);
}
mHandler = new Handler();
btleGattCallback = new BluetoothGattCallback() {
#Override
// Result of a characteristic read operation
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
#Override
public void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) {
Log.w("doscover", "Connected " + status);
}
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
Log.w("discover", "onServicesDiscovered received: " + status);
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
} else {
Log.w("doscover", "onServicesDiscovered received: " + status);
}
}
};
devicefound = new ArrayList<BluetoothDevice>();
devices = new ArrayAdapter<String>( this , R.layout.device_name);
ListView pairedListView = (ListView) findViewById(R.id.textView3);
pairedListView.setAdapter(devices);
mleScanCallback = new BluetoothAdapter.LeScanCallback() {
#Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
devicefound.add(device);
//UUID = device.getAddress().toString();
//Log.e("Search", "" + device.getName().toString() );
//Toast`.makeText(context,device.getName().toString(), 1 ).show();
Log.e("Search", "" + device.toString());
Log.e("Search", "" + String.valueOf(rssi) );
devices.add("Nex" + device.getName() );
//mBluetoothGatt = device.connectGatt(getActivity(), true, btleGattCallback);
}
};
pairedListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View arg1,
int position, long id) {
dv = devicefound.get(position);
mBluetoothGatt = dv.connectGatt(getApplicationContext() , true, btleGattCallback);
mBluetoothGatt.connect();
dv.createBond();
//BluetoothDevice dd = madapter.getRemoteDevice(devicefound.get(position).getAddress());
if(i == false)
{
Toast.makeText(getApplicationContext(), "Service found. Connected to " + dv.getName() , 1).show();
}
else
{
Toast.makeText(getApplicationContext(), "Already Connected " + dv.getName() , 1).show();
}
i = mBluetoothGatt.connect();
mBluetoothGatt.beginReliableWrite();
boolean b = mBluetoothGatt.discoverServices();
Log.e("Discovery Started", "" + b );
Log.e("get ItemATPosition", "" + adapter.getItemAtPosition(position));
//BluetoothGattService Service = mBluetoothGatt.getService( );
// = Service.getCharacteristic(k);
BluetoothGattCharacteristic characteristic= new BluetoothGattCharacteristic(k,2,1); //Service
characteristic.setValue( "This is a Charects ");
byte[] value = {(byte)91,(byte)92,(byte)93};
characteristic.setValue(value);
boolean st = mBluetoothGatt.writeCharacteristic(characteristic);
//Toast.makeText(getActivity(), t1.getText() + " " + st, 1).show();
boolean b1 = mBluetoothGatt.executeReliableWrite();
//Toast.makeText(getActivity(), t1.getText() + " " + b1, 1).show();
Intent in = new Intent("ACTION_BOND_STATE_CHANGED.");
sendBroadcast(in);
}
});
scanLeDevice(true);
I'm using the writeCharacteristic command of the connected Gatt from central but dont know how to receive from Peripheral end
Any sort of Help will be appreciated.
peripheral mode may support good on IOS, I suggest you use light blue for test purpose, from here:https://itunes.apple.com/us/app/lightblue-bluetooth-low-energy/id557428110?mt=8
and as I know Lollipop 5 installed on nexus 6 and nexus 9 can support peripheral mode, nexus 5 do not support it.
Moto G support peripheral mode?