I had done lot of R&D on getting the incoming number when calling is done from the Twilio number to the other Twilio number in the app using Twilio as a third party integration.
But i do not get anything regarding that incoming number, I got the call from the other Twilio number, device is listening to the incoming call, but could not able to identify the incoming number, for that I am using this method connectionCall.IncomingParameterFromKey, it only return me "From".
Below is the code for receiving the call in the app using Twilio integration.
public class Call_Answer extends Activity implements OnClickListener{
String sub_sid="",sub_auth_token="",call_from="";
SharedPreferences sharedPref;
SharedPreferences.Editor prefEdit;
TextView callanswer_btn,callreject_btn;
private Connection connectionCall;
IncomingCall phone;
private Device device;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Method onCreate created by vk hooda on Oct 30, 2012
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.callanswer);
sharedPrefValues();
initializeView();
}
private void sharedPrefValues() {
// Method sharedPrefValues created by vk hooda on Oct 31, 2012
sharedPref=PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
prefEdit=sharedPref.edit();
sub_sid=sharedPref.getString(Constant_Variables.using_sub_sid,"");
sub_auth_token=sharedPref.getString(Constant_Variables.using_sub_auth_token,"");
call_from=sharedPref.getString(Constant_Variables.using_phone_number, "");
//Initialize Calls
phone=new IncomingCall(sub_sid,sub_auth_token,call_from,getApplicationContext());
//phone=new IncomingCall(Constants.account_SID,Constants.account_Token,Constants.karl_number,getApplicationContext());
}
private void initializeView() {
// Method initializeView created by vk hooda on Oct 30, 2012
callanswer_btn=(TextView)findViewById(R.id.callanswer_btn);
callreject_btn=(TextView)findViewById(R.id.callreject_btn);
callanswer_btn.setOnClickListener(this);
callreject_btn.setOnClickListener(this);
}
#Override
public void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
setIntent(intent);
}
#Override
public void onResume()
{
super.onResume();
Intent intent = getIntent();
Device device = intent.getParcelableExtra(Device.EXTRA_DEVICE);
Connection connection = intent.getParcelableExtra(Device.EXTRA_CONNECTION);
if (device != null && connection != null) {
intent.removeExtra(Device.EXTRA_DEVICE);
intent.removeExtra(Device.EXTRA_CONNECTION);
handleIncomingConnection(device, connection);
// ringingPhone(intent);
}
}
public void handleIncomingConnection(Device inDevice, Connection inConnection)
{
Log.i("Handle incoming call", "Device received incoming connection");
connectionCall=inConnection;
device=inDevice;
if (connectionCall != null)
{
connectionCall.disconnect();
connectionCall = inConnection;
// connectionCall.reject();
Log.i("Blocktimer.blocking_call",""+Blocktimer.blocking_call);
if(Blocktimer.blocking_call == true)
{
connectionCall.reject();
Blocktimer.blocking_call = false;
}
Log.i("connectionIIIIII",""+ connectionCall.IncomingParameterAccountSIDKey);
Log.i("connectionIIIIII",""+ connectionCall.IncomingParameterAPIVersionKey);
Log.i("connectionIIIIII",""+ connectionCall.IncomingParameterCallSIDKey);
Log.i("connectionIIIIII",""+ connectionCall.IncomingParameterFromKey);
Log.i("connectionIIIIII",""+ connectionCall.IncomingParameterToKey);
Log.i("connectionIIIIII",""+ connectionCall.hashCode());
Log.i("connectionIIIIII",""+ connectionCall.CONTENTS_FILE_DESCRIPTOR);
Log.i("connectionIIIIII",""+ connectionCall.PARCELABLE_WRITE_RETURN_VALUE);
Log.i("connectionIIIIII",""+ connectionCall.getState());
Log.i("connectionIIIIII",""+ connectionCall.isIncoming());
Log.i("connectionIIIIII",""+ connectionCall.isMuted());
Log.v("Handling Incoming Call","Someone calling you.you have accepted it here.");
}
}
public void onClick(View v) {
// Method onClick created by vk hooda on Oct 30, 2012
if(v==callanswer_btn)
{
if (connectionCall != null)
{
connectionCall.accept();
Log.i("connectionaccept",""+ connectionCall.getState());
Log.v("calling answer","Conversation start.....");
}
}
if(v==callreject_btn)
{
//connectionCall.disconnect();
Log.v("calling disconnect","Conversation disconnect.....");
if (connectionCall != null)
{
connectionCall.disconnect();
Log.i("connectionReject",""+ connectionCall.getState());
connectionCall=null;
Log.v("Disconnect","Disconnecting in finalize method");
}
if (device != null)
{
Log.v("Disconnect","Release in finalize method");
device.release();
device=null;
}
finish();
}
}
}
I had also faced the same problem and I rectified by using this code
connection.IncomingParameterFromKey will returns you the parameter name only you need to pass that name to connection parameters.
code :
connection.getParameters().get(connection.IncomingParameterFromKey).replace("%2B", "");
Related
I'm making an Android app that is supposed to connect to a BLE-module and should be able to read it's services and characteristics. My app is based on the code of Accent Systems' "iBKS Hello World" application.
I am not using iBeacons, but a different kind of BLE-module. But when I connect to it, the app is not showing a list of services and characteristics as the code indicates should happen.
Can anyone help me fix this problem? Please let me know!
My code:
public class ScanActivity extends AppCompatActivity {
//DEFINE VARS
String TAG = "ScanActivity";
BluetoothAdapter mBluetoothAdapter;
BluetoothGatt mBluetoothGatt;
BluetoothLeScanner scanner;
ScanSettings scanSettings;
private List<String> scannedDeivcesList;
private ArrayAdapter<String> adapter;
//DEFINE LAYOUT
ListView devicesList;
//THIS METHOD RUNS ON APP LAUNCH
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan);
//Define listview in layout
devicesList = (ListView) findViewById(R.id.devicesList);
//Setup list on device click listener
setupListClickListener();
//Initialize de devices list
scannedDeivcesList = new ArrayList<>();
//Initialize the list adapter for the listview with params: Context / Layout file / TextView ID in layout file / Devices list
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, scannedDeivcesList);
//Set the adapter to the listview
devicesList.setAdapter(adapter);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
SpannableString s = new SpannableString("Scan for modules");
s.setSpan(new com.accent_systems.ibkshelloworld.TypefaceSpan(this, "Khand-Bold.ttf"), 0, s.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
s.setSpan(new ForegroundColorSpan(Color.parseColor("#3a3c3e")), 0, s.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
setTitle(s);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
//init Bluetooth adapter
initBT();
//Start scan of bluetooth devices
startLeScan(true);
}
#Override
protected void onStop() {
super.onStop();
startLeScan(false);
}
private void initBT(){
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//Create the scan settings
ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder();
//Set scan latency mode. Lower latency, faster device detection/more battery and resources consumption
scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
//Wrap settings together and save on a settings var (declared globally).
scanSettings = scanSettingsBuilder.build();
//Get the BLE scanner from the BT adapter (var declared globally)
scanner = mBluetoothAdapter.getBluetoothLeScanner();
}
private void startLeScan(boolean endis) {
if (endis) {
//********************
//START THE BLE SCAN
//********************
//Scanning parameters FILTER / SETTINGS / RESULT CALLBACK. Filter are used to define a particular
//device to scan for. The Callback is defined above as a method.
scanner.startScan(null, scanSettings, mScanCallback);
}else{
//Stop scan
scanner.stopScan(mScanCallback);
}
}
private ScanCallback mScanCallback = new ScanCallback() {
#Override
public void onScanResult(int callbackType, ScanResult result) {
super.onScanResult(callbackType, result);
//Here all the detected BLE devices will be received . "result" contains the device
//address and name as a BLEPeripheral, the advertising content as a ScanRecord, the Rx RSSI
//and the timestamp when received. Type result.get... to see all the available methods you can call.
//Convert advertising bytes to string for a easier parsing. GetBytes may return a NullPointerException. Treat it right(try/catch).
String advertisingString = byteArrayToHex(result.getScanRecord().getBytes());
//Print the advertising String in the LOG with other device info (ADDRESS - RSSI - ADVERTISING - NAME)
Log.i(TAG, result.getDevice().getAddress()+" - RSSI: "+result.getRssi()+"\t - "+advertisingString+" - "+result.getDevice().getName());
//Check if scanned device is already in the list by mac address
boolean contains = false;
for(int i=0; i<scannedDeivcesList.size(); i++){
if(scannedDeivcesList.get(i).contains(result.getDevice().getAddress())){
//Device already added
contains = true;
//Replace the device with updated values in that position
scannedDeivcesList.set(i, result.getRssi()+" "+result.getDevice().getName()+ "\n ("+result.getDevice().getAddress()+")");
break;
}
}
if(!contains){
//Scanned device not found in the list. NEW => add to list
scannedDeivcesList.add(result.getRssi()+" "+result.getDevice().getName()+ "\n ("+result.getDevice().getAddress()+")");
}
//After modify the list, notify the adapter that changes have been made so it updates the UI.
//UI changes must be done in the main thread
runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
}
};
//Method to convert a byte array to a HEX. string.
private String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
void setupListClickListener(){
devicesList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//Stop the scan
Log.i(TAG, "SCAN STOPPED");
scanner.stopScan(mScanCallback);
//Get the string from the item clicked
String fullString = scannedDeivcesList.get(position);
//Get only the address from the previous string. Substring from '(' to ')'
String address = fullString.substring(fullString.indexOf("(")+1, fullString.indexOf(")"));
//Get BLE device with address
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
//******************************
//START CONNECTION WITH DEVICE AND DECLARE GATT
//******************************
Log.i(TAG,"*************************************************");
Log.i(TAG, "CONNECTION STARTED TO DEVICE "+address);
Log.i(TAG,"*************************************************");
//ConnectGatt parameters are CONTEXT / AUTOCONNECT to connect the next time it is scanned / GATT CALLBACK to receive GATT notifications and data
// Note: On Samsung devices, the connection must be done on main thread
mBluetoothGatt = device.connectGatt(ScanActivity.this, false, mGattCallback);
/*
There is also another simplest way to connect to a device. If you already stored
the device in a list (List<BluetoothDevice>) you can retrieve it directly and
connect to it:
mBluetoothGatt = mList.get(position).connectGatt(MainActivity.this, false, mGattCallback);
*/
}
});
}
//Connection callback
BluetoothGattCallback mGattCallback =
new BluetoothGattCallback() {
#Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
//Device connected, start discovering services
Log.i(TAG, "DEVICE CONNECTED. DISCOVERING SERVICES...");
mBluetoothGatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
//Device disconnected
Log.i(TAG, "DEVICE DISCONNECTED");
}
}
// On discover services method
#Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//Services discovered successfully. Start parsing services and characteristics
Log.i(TAG, "SERVICES DISCOVERED. PARSING...");
displayGattServices(gatt.getServices());
} else {
//Failed to discover services
Log.i(TAG, "FAILED TO DISCOVER SERVICES");
}
}
//When reading a characteristic, here you receive the task result and the value
#Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
//READ WAS SUCCESSFUL
Log.i(TAG, "ON CHARACTERISTIC READ SUCCESSFUL");
//Read characteristic value like:
//characteristic.getValue();
//Which it returns a byte array. Convert it to HEX. string.
} else {
Log.i(TAG, "ERROR READING CHARACTERISTIC");
}
}
//When writing, here you can check whether the task was completed successfully or not
#Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.i(TAG, "ON CHARACTERISTIC WRITE SUCCESSFUL");
} else {
Log.i(TAG, "ERROR WRITING CHARACTERISTIC");
}
}
//In this method you can read the new values from a received notification
#Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
Log.i(TAG, "NEW NOTIFICATION RECEIVED");
//New notification received. Check the characteristic it comes from and parse to string
/*if(characteristic.getUuid().toString().contains("0000fff3")){
characteristic.getValue();
}*/
}
//RSSI values from the connection with the remote device are received here
#Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
Log.i(TAG, "NEW RSSI VALUE RECEIVED");
//Read remote RSSI like: mBluetoothGatt.readRemoteRssi();
//Here you get the gatt table where the rssi comes from, the rssi value and the
//status of the task.
}
};
//Method which parses all services and characteristics from the GATT table.
private void displayGattServices(List<BluetoothGattService> gattServices) {
//Check if there is any gatt services. If not, return.
if (gattServices == null) return;
// Loop through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
Log.i(TAG, "SERVICE FOUND: "+gattService.getUuid().toString());
//Loop through available characteristics for each service
for (BluetoothGattCharacteristic gattCharacteristic : gattService.getCharacteristics()) {
Log.i(TAG, " CHAR. FOUND: "+gattCharacteristic.getUuid().toString());
}
}
//****************************************
// CONNECTION PROCESS FINISHED!
//****************************************
Log.i(TAG, "*************************************");
Log.i(TAG, "CONNECTION COMPLETED SUCCESFULLY");
Log.i(TAG, "*************************************");
}
}
You may find full description here. And here short example. So you bring list of services after BLE connection and services request. Later you may request characteristics for every service. Main idea when you bring services one by one you have it UUID and reference. If you have know some service that you like to use you should know it before bring all services. And on collecting them save somewhere reference of service test every by known UUID. Later use this reference for bring characteristics and interconnection with device.
I want my app to auto-connect to already connected bluetooth device on restarting the app. Below is procedure I am performing:-
[Initially] Bluetooth device is 'ON': Then on starting the app.
[Behavior]--> Bluetooth device gets paired and connected successfully ( Intent 'ACTION_ACL_CONNECTED' is received)
Bluetooth device is 'ON': Closed the app, then started the app again.
[Behavior]--> Even though it is connected as displayed on Bluetooth setting, and Broadcast Receiver does not receive Intent 'ACTION_ACL_CONNECTED'.
Note:- On closing the app, it does not disconnect the bluetooth connection.
So, on successful connection app straightaway goes to the HomeScreen. Otherwise, the app goes to a screen having button that takes it to Bluetooth setting(onClickListener present in the code below)
I am new to android development, so I really don't know where am I going wrong. I looked up the solutions for similar issues and applied them, but to no effect.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
registerReceiver(mReceiver, filter);
IntentFilter filter1 = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter1);
m_app = (BtApp) getApplication();
imagebt = (ImageView) this.findViewById(R.id.imagebt);
imagebt.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final Toast tag = Toast.makeText(getApplicationContext(), "Connect to device", Toast.LENGTH_LONG);
tag.show();
new CountDownTimer(1000, 1000)
{
public void onTick(long millisUntilFinished) {tag.show();}
public void onFinish() {
//tag.show();
}
}.start();
if(mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()){
mBluetoothAdapter.startDiscovery();
}
Intent intentBluetooth = new Intent();
intentBluetooth.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intentBluetooth);
}
});
}
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ( BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
m_app.m_main.setupCommPort();
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
m_app.m_device = device;
isconnected = true;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
if ( m_app.m_main.m_BtService != null && m_app.m_main.m_BtService.getState() != BluetoothRFCommService.STATE_CONNECTED ) {
m_app.m_main.m_BtService.connect(device, false);
}
}
}, 3500);
} else if ( BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action) ) {
isconnected = false;
m_app.m_main.tabHost.setCurrentTab(0);
}
}
};
#Override
protected void onStop()
{
unregisterReceiver(mReceiver);
super.onStop();
}
You won't get BluetoothDevice.ACTION_ACL_CONNECTED event since the device is still connected. The event is fired only on changing of device state from disconnected to connected.
You have 2 options.
You can put your BroadcastReceiver with BluetoothDevice.ACTION_ACL_CONNECTED and BluetoothDevice.ACTION_ACL_DISCONNECTED filters into the Service and track the device connection state in the background. On your app startup you can ask the service to give you the current state of the device.
You can check if some of the Bluetooth profiles contains your device name in the list of connected devices.
For API 18+ you can use BluetoothManager#getConnectedDevices() for API below 18 you can use the following snippet (for each Bluetooth profile)
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
for (BluetoothDevice device : proxy.getConnectedDevices()) {
if (device.getName().contains("DEVICE_NAME")) {
deviceConnected = true;
}
}
if (!deviceConnected) {
Toast.makeText(getActivity(), "DEVICE NOT CONNECTED", Toast.LENGTH_SHORT).show();
}
mBluetoothAdapter.closeProfileProxy(profile, proxy);
}
public void onServiceDisconnected(int profile) {
// TODO
}
};
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.A2DP);
Background
I am creating a service that syncs a local Realm database (stored on phone) with an online database. The database stores users and measurements.
I initialise the service by calling 'startService(new Intent(this, SyncService.class));' during the splash activity's onCreate() method, and specify in the manifest that the service should run for the length of the application.
The service has a broadcast receiver. When the receiver detects a network change from 'not connected' to 'connected', it fires a method called syncDatabases().
This method finds all measurements recorded locally after the timestamp of the last API callback, and sends them to the database. The API responds to a request by returning the object + a unique ID.
When a measurement is made whilst the device is offline, it is stored locally. When an internet connection is made, the syncDatabases() method should be called in order to update the online server with the local measurements.
My steps...
Steps when debugging the project:
With wifi I open the app and with an external device make a new measurement. This appears on both the app and in the database. I then turn wifi off and make another measurement - this appears on the device.
I attach the debugger.
I turn back on wifi and this triggers the services' receivers' onReceive() method. I step through this and it all works according to plan. I reach the syncDatabases() method, and from there I receive the callback from the API, and it then updates the Realm database with the new ID value.
The problem...
If I don't attach the debugger, nothing happens. The new measurements aren't pushed to the database, and none of my Log.e calls are printed.
Why is this happening? And is there an alternative solution / fix for this problem?
Code
Service class
public class SyncService extends Service {
private static final String TAG = "SYNCSERVICE";
private boolean mConnected = false;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras() != null) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
switch (netInfo.getState()) {
case CONNECTED:
if (!mConnected) {
Log.e("NETWORK", "Network " + netInfo.getTypeName() + " now connected");
syncDatabases();
mConnected = true;
}
break;
default:
mConnected = false;
break;
}
} else mConnected = false;
}
}
};
#Override
public void onCreate() {
super.onCreate();
initReceiver();
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() != null) {
mConnected = true;
}
android.util.Log.e(TAG, "onCreate: SyncService created");
}
#Override
public void onDestroy() {
super.onDestroy();
unInitReceiver();
android.util.Log.e(TAG, "onDestroy: SyncService destroyed");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
android.util.Log.e(TAG, "onBind: SyncService bound");
return null;
}
#Override
public boolean onUnbind(Intent intent) {
android.util.Log.e(TAG, "onUnbind: SyncService unbound");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
android.util.Log.e(TAG, "onRebind: SyncService rebound");
}
private void initReceiver() {
IntentFilter filters = new IntentFilter();
filters.addAction("android.net.wifi.WIFI_STATE_CHANGED");
filters.addAction("android.net.wifi.STATE_CHANGE");
registerReceiver(mReceiver, filters);
}
private void unInitReceiver() {
unregisterReceiver(mReceiver);
}
public void syncDatabases() {
RealmResults<UserDB> users = RealmDB.getInstance(getApplicationContext()).where(UserDB.class).findAll();
if (users.size() > 0) {
int userId = users.get(0).getmUserID();
Log.e("MESSAGE", PreferenceUtils.getInstance().getLastSyncDate());
Date lastSync = null;
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault());
try {
lastSync = sdf.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e) {
e.printStackTrace();
try {
lastSync = BaseFragment.FORMAT.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e1) {
e1.printStackTrace();
}
}
if (lastSync != null) {
Date lastSyncOffset = new Date(lastSync.getTime() + 1000);
/** Get all local results which have been made after the last sync date
**/
RealmResults<MeasurementDB> newLocalMeasurements = RealmDB.getInstance(getApplicationContext())
.where(MeasurementDB.class).equalTo("user_ID", userId)
.greaterThan("dateCreated", lastSyncOffset)
.findAll();
/** For each measurement made after the last sync, add it to the server
**/
for (MeasurementDB measurement : newLocalMeasurements) {
TemperatureListener mListener = new TemperatureListener(measurement);
ApiRequest.getInstance(getApplicationContext()).registerNewMeasurement(measurement.getAverage(),
measurement.getDateCreated().toString(), mListener, mListener);
}
}
}
}
/**
* Temperature listener receives the local copy of the temperature item. onResponse can then
* directly mutate the object instead of searching local db
*/
private class TemperatureListener implements Response.Listener<Measurement>, Response.ErrorListener {
private MeasurementDB measurement;
public TemperatureListener(MeasurementDB measurement) {
this.measurement = measurement;
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e("OnResponse", "Failure");
}
#Override
public void onResponse(Measurement response) {
Log.e("OnResponse", "Success");
/** Update our local measurement's ID value (supplied by server)
**/
RealmDB.getInstance(getApplicationContext()).beginTransaction();
measurement.setMeasurement_ID(response.getmMeasurementId());
RealmDB.getInstance(getApplicationContext()).commitTransaction();
/** Update the last sync date
**/
PreferenceUtils.getInstance().setLastSyncDate(response.getmDateCreated());
}
}
}
Initialisation of Service in splash activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mTimedOut = true;
finishActivity();
}
}, DURATION);
/** Will sync application / cloud databases in background of app when network connected. **/
startService(new Intent(this, SyncService.class));
doApiWork();
}
Manifest entry
Stop with task to kill the service at the same time as the app.
Exported 'false' stops other apps from using the service.
<service
android:name=".network.SyncService"
android:stopWithTask="true"
android:enabled="true"
android:exported="false"/>
EDIT
I removed the service and left a receiver class, registered in the manifest, which triggers methods on another class when needed. However the receiver is only triggered in debug mode.
I am trying to develop an Android application, which can access the current location of my phone and send it to my friend with URL.
So I use location object mLocation to access latitude and longitude of my location. FectchAddressIntentService.java is a service to obtain location address.
But it gives an error:
java.lang.IllegalArguementException:Attempt to invoke virtual method 'double android.Location.getlatitude()' on a null object reference
Here is the code of my MainActivity.java:
public class MainActivity extends AppCompatActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
protected static final String TAG = "main-activity";
protected static final String ADDRESS_REQUESTED_KEY = "address-request-pending";
protected static final String LOCATION_ADDRESS_KEY = "location-address";
protected String message;
protected String phoneNo = "1234567890";
public void sendMessage() {
try {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(phoneNo, null, message, null, null);
Toast.makeText(MainActivity.this,"Sending SMS",Toast.LENGTH_LONG).show();
}
catch (Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG);
}
}
public void startGuardianActivity(){
Intent intentViewGuardian = new Intent(this, Guardians.class);
startActivity(intentViewGuardian);
}
/**
* Provides the entry point to Google Play services.
*/
protected GoogleApiClient mGoogleApiClient;
/**
* Represents a geographical location.
*/
protected Location mLastLocation;
protected String latitude;
protected String longitude;
/**
* Tracks whether the user has requested an address. Becomes true when the user requests an
* address and false when the address (or an error message) is delivered.
* The user requests an address by pressing the Fetch Address button. This may happen
* before GoogleApiClient connects. This activity uses this boolean to keep track of the
* user's intent. If the value is true, the activity tries to fetch the address as soon as
* GoogleApiClient connects.
*/
protected boolean mAddressRequested;
/**
* The formatted location address.
*/
protected String mAddressOutput;
/**
* Receiver registered with this activity to get the response from FetchAddressIntentService.
*/
private AddressResultReceiver mResultReceiver;
/**
* Kicks off the request to fetch an address when pressed.
*/
Button btnAlert;
Button btnAddGuardian;
Button btnRemoveGuardian;
Button btnViewGuardians;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
mResultReceiver = new AddressResultReceiver(new Handler());
btnAlert = (Button) findViewById(R.id.btn_Alert);
btnAddGuardian = (Button) findViewById(R.id.btn_add_guardian);
btnRemoveGuardian = (Button) findViewById(R.id.btn_remove_guardian);
btnViewGuardians = (Button) findViewById(R.id.btn_view_guardians);
btnAddGuardian.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
btnRemoveGuardian.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
btnViewGuardians.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startGuardianActivity();
}
});
// Set defaults, then update using values stored in the Bundle.
mAddressRequested = false;
mAddressOutput = "";
updateValuesFromBundle(savedInstanceState);
updateUIWidgets();
buildGoogleApiClient();
}
/**
* Updates fields based on data stored in the bundle.
*/
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Check savedInstanceState to see if the address was previously requested.
if (savedInstanceState.keySet().contains(ADDRESS_REQUESTED_KEY)) {
mAddressRequested = savedInstanceState.getBoolean(ADDRESS_REQUESTED_KEY);
}
// Check savedInstanceState to see if the location address string was previously found
// and stored in the Bundle. If it was found, display the address string in the UI.
if (savedInstanceState.keySet().contains(LOCATION_ADDRESS_KEY)) {
mAddressOutput = savedInstanceState.getString(LOCATION_ADDRESS_KEY);
displayAddressOutput();
}
}
}
/**
* Builds a GoogleApiClient. Uses {#code #addApi} to request the LocationServices API.
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
/**
* Runs when user clicks the Fetch Address button. Starts the service to fetch the address if
* GoogleApiClient is connected.
*/
public void fetchAddressButtonHandler(View view) {
// We only start the service to fetch the address if GoogleApiClient is connected.
if (mGoogleApiClient.isConnected() && mLastLocation != null) {
startIntentService();
}
// If GoogleApiClient isn't connected, we process the user's request by setting
// mAddressRequested to true. Later, when GoogleApiClient connects, we launch the service to
// fetch the address. As far as the user is concerned, pressing the Fetch Address button
// immediately kicks off the process of getting the address.
mAddressRequested = true;
updateUIWidgets();
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
protected void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Runs when a GoogleApiClient object successfully connects.
*/
#Override
public void onConnected(Bundle connectionHint) {
// Gets the best and most recent location currently available, which may be null
// in rare cases when a location is not available.
try {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
}
catch(Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG).show();
}
try {
if (mLastLocation != null) {
if (!Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
}
}
catch(Exception e)
{
Toast.makeText(MainActivity.this,e.toString(),Toast.LENGTH_LONG).show();
}
// It is possible that the user presses the button to get the address before the
// GoogleApiClient object successfully connects. In such a case, mAddressRequested
// is set to true, but no attempt is made to fetch the address (see
// fetchAddressButtonHandler()) . Instead, we start the intent service here if the
// user has requested an address, since we now have a connection to GoogleApiClient.
if (mAddressRequested) {
startIntentService();
}
}
/**
* Creates an intent, adds location data to it as an extra, and starts the intent service for
* fetching an address.
*/
protected void startIntentService() {
// Create an intent for passing to the intent service responsible for fetching the address.
Intent intent = new Intent(this, FetchAddressIntentService.class);
// Pass the result receiver as an extra to the service.
intent.putExtra(Constants.RECEIVER, mResultReceiver);
// Pass the location data as an extra to the service.
intent.putExtra(Constants.LOCATION_DATA_EXTRA, mLastLocation);
// Start the service. If the service isn't already running, it is instantiated and started
// (creating a process for it if needed); if it is running then it remains running. The
// service kills itself automatically once all intents are processed.
startService(intent);
}
#Override
public void onConnectionFailed(ConnectionResult result) {
// Refer to the javadoc for ConnectionResult to see what error codes might be returned in
// onConnectionFailed.
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
}
#Override
public void onConnectionSuspended(int cause) {
// The connection to Google Play services was lost for some reason. We call connect() to
// attempt to re-establish the connection.
Log.i(TAG, "Connection suspended");
mGoogleApiClient.connect();
}
/**
* Updates the address in the UI.
*/
protected void displayAddressOutput() {
sendMessage();
}
private void updateUIWidgets() {
if (mAddressRequested) {
btnAlert.setEnabled(false);
} else {
btnAlert.setEnabled(true);
}
}
/**
* Shows a toast with the given text.
*/
protected void showToast(String text) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save whether the address has been requested.
savedInstanceState.putBoolean(ADDRESS_REQUESTED_KEY, mAddressRequested);
// Save the address string.
savedInstanceState.putString(LOCATION_ADDRESS_KEY, mAddressOutput);
super.onSaveInstanceState(savedInstanceState);
}
/**
* Receiver for data sent from FetchAddressIntentService.
*/
class AddressResultReceiver extends ResultReceiver {
public AddressResultReceiver(Handler handler) {
super(handler);
}
/**
* Receives data sent from FetchAddressIntentService and updates the UI in MainActivity.
*/
#Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
// Display the address string or an error message sent from the intent service.
mAddressOutput = resultData.getString(Constants.RESULT_DATA_KEY);
message = "I am in DANGER!!I need your help #"+mAddressOutput+" link: http://maps.google.com/?q="+latitude+","+longitude;
displayAddressOutput();
// Show a toast message if an address was found.
if (resultCode == Constants.SUCCESS_RESULT) {
showToast(getString(R.string.address_found));
}
mAddressRequested = false;
updateUIWidgets();
}
}
}
I tried to convert
latitude = String.valueOf(mLastLocation.getLatitude());
to
longitude = String.valueOf(mLastLocation.getLongitude());
But didn't work.
I don't know what this error is, I don`t know what NullPointerException is,
I tried to follow other Questions on Stack Overflow of similar type but didn't solve problem, Can anyone help me to get through this?
Even if you feel it might be a duplicate of other question, tell me how it is or how they are related & how to solve my problem. Thanks in advance.:-)
The error means the valiable mLastLocation is null.
So the result of this line:
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
is null. I think you should null check before these lines:
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
Because they are calling methods of mLastLocation.
That is like:
if (mLastLocation == null || !Geocoder.isPresent()) {
Toast.makeText(this, R.string.no_geocoder_available, Toast.LENGTH_LONG).show();
return;
}
latitude = String.valueOf(mLastLocation.getLatitude());
longitude = String.valueOf(mLastLocation.getLongitude());
I am making a simple client-server application which can be used to transfer integers, strings or characters.
My application compiled successfully, but no client-server connection is there.
When I try to search for a server, it gives the NullPointerException on the line
bluetooth.startDiscovery();
However, when I start the server it gives no exception.
Also, when I start a server on one device and look for a server on another, a connection is not established either due to a problem in server running correctly or a problem in the client.
I have already got an instance of BluetoothAdapter using
bluetooth = BluetoothAdapter.getDefaultAdapter();
I think that probably a null pointer is given because i am calling the method startDiscovery() inside an onclickListener, this one,
private void setupSearchButton() {
Button searchButton = (Button) findViewById(R.id.button_search);
searchButton.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
registerReceiver(discoveryResult, new IntentFilter(BluetoothDevice.ACTION_FOUND));
if (!bluetooth.isDiscovering()) {
try { foundDevices.clear();
bluetooth.startDiscovery(); } catch(Exception e)
{
Context c = getApplicationContext();
Toast.makeText(c, e.toString(),Toast.LENGTH_LONG).show();
}
}
}
});
}
The code for declaring a server is posted here :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DISCOVERY_REQUEST) {
boolean isDiscoverable = resultCode > 0;
if (isDiscoverable) {
String name = "bluetoothserver";
try {
final BluetoothServerSocket btserver = bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);
AsyncTask<Integer, Void, BluetoothSocket> acceptThread = new AsyncTask<Integer, Void, BluetoothSocket>() {
#Override
protected BluetoothSocket doInBackground(Integer... params) {
try {
socket = btserver.accept(params[0] * 1000);
return socket;
} catch (Exception e) {
Log.d("BLUETOOTH SERVER EXCEPTION : ", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(BluetoothSocket result) {
if (result != null) {
switchUI();
}
}
};
acceptThread.execute(resultCode);
} catch (IOException e) {
Log.d("BLUETOOTH", e.getMessage());
}
}
}
}
Can someone tell me what is the problem ? I am using two buttons, one to start a bluetooth server and other to search for a bluetooth server. The method that runs on clicking the start bluetooth server button triggers startActivityForResult, as a result of which the method onActivityResult is executed as shown here. The OnClickListener for search server button is already shown here.