How to get the result from a call to google services? - java

I'm trying to get the location with the google-location services for android.
I've tried to fiddle with some methods from the google api from the tasks package, but all seem to fail. More exactly, my application starts to hang.
public class LocationTask extends AsyncTask<FusedLocationProviderClient, Void, JSONObject> {
#SuppressLint("MissingPermission")
#Override
protected JSONObject doInBackground(FusedLocationProviderClient... locationProviderClients) {
WeatherApiCall weatherApiCall = new WeatherApiCall();
Task<Location> locationTask = locationProviderClients[0].getLastLocation();
Location location = null ;
try {
location = Tasks.await(locationTask);
weatherApiCall.execute("weather", String.format(Locale.getDefault(), "%.2f", location.getLatitude()),
String.format(Locale.getDefault(), "%.2f", location.getLongitude()), "metric");
return new JSONObject(weatherApiCall.get());
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
I've also tried to use the addOnSuccessListener, but to no avail.
try {
locationProviderClients[0].getLastLocation()
.addOnSuccessListener(location -> {
if (location != null) {
Log.d("LOCATION", location.toString());
weatherApiCall.execute("weather", String.format(Locale.getDefault(), "%.2f", location.getLatitude()),
String.format(Locale.getDefault(), "%.2f", location.getLongitude()), "metric");
}
});
return new JSONObject(weatherApiCall.get());
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
I know that the success listener does the action after the task locationProviderClients[0].getLastLocation() is successfully completed, but I fail to get the result from the task.

Related

Android doInBackground error

I am a beginner in android development and I get an error that I can not solve a few days ago with the doInBackground() method.
My error is at the end of my code, at
e2 = e11;
createInsecureRfcommSocketToServiceRecord = null;
this.sender = e2.getMessage();
createInsecureRfcommSocketToServiceRecord.close();
The error is
Unhandled exception:java.io.IO.EXCEPTION
If you have solutions , thank you in advance!
My code :
protected Object doInBackground(Object[] objArr) {
BluetoothSocket createInsecureRfcommSocketToServiceRecord;
IOException e;
Throwable th;
IButton a;
Boolean valueOf;
boolean z = true;
this.jobType = (JobType) objArr[0];
this.sender = (MainActivity) objArr[1];
this.device = (BluetoothDevice) objArr[2];
try {
createInsecureRfcommSocketToServiceRecord =
device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
try {
createInsecureRfcommSocketToServiceRecord.connect();
} catch (IOException e2) {
Log.e("Bluetooth", e2.getMessage());
Log.e("Bluetooth", "trying fallback");
try {
createInsecureRfcommSocketToServiceRecord = (BluetoothSocket)
this.device.getClass().getMethod("createInsecureRfcommSocket", new Class[]{Integer.TYPE}).invoke(this.device, new Object[]{Integer.valueOf(1)});
} catch (Exception e3) {
Log.e("Bluetooth", e3.getMessage());
}
try {
createInsecureRfcommSocketToServiceRecord.connect();
} catch (IOException e4) {
e2 = e4;
try {
this.error = e2.getMessage();
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e5) {
}
return null;
} catch (Throwable th2) {
th = th2;
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e6) {
}
throw th;
}
}
}
if (this.jobType == JobType.read) {
a = readDevice(createInsecureRfcommSocketToServiceRecord);
try {
createInsecureRfcommSocketToServiceRecord.close();
return a;
} catch (IOException e7) {
return a;
}
} else
if (this.jobType == JobType.stopMission) {
a = (IButton) objArr[3];
if (!(stopMission(createInsecureRfcommSocketToServiceRecord) &&
writeDevice(createInsecureRfcommSocketToServiceRecord, a))) {
z = false;
}
valueOf = Boolean.valueOf(z);
try {
createInsecureRfcommSocketToServiceRecord.close();
return valueOf;
} catch (IOException e8) {
return valueOf;
}
} else
if (this.jobType == JobType.startMission) {
boolean z2 = writeDevice(createInsecureRfcommSocketToServiceRecord, (IButton) objArr[3]) &&
startMission(createInsecureRfcommSocketToServiceRecord);
valueOf = Boolean.valueOf(z2);
try {
createInsecureRfcommSocketToServiceRecord.close();
return valueOf;
} catch (IOException e9) {
return valueOf;
}
} else {
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e10) {
}
return null;
}
} catch (IOException e11) {
e2 = e11;
createInsecureRfcommSocketToServiceRecord = null;
this.sender = e2.getMessage();
createInsecureRfcommSocketToServiceRecord.close();
return null;
} catch (Throwable th3) {
th = th3;
createInsecureRfcommSocketToServiceRecord = null;
createInsecureRfcommSocketToServiceRecord.close();
throw th;
}
return null;
}
close() also throws an IOException exception you need to handle. Additionally you should use a finally block for cleaning up and be careful not to provoke NullPointerExeptions by setting the variable to null before closing it.
You could improve your code like
try {
....
} catch (Exception e) {
....
} finally {
try {
createInsecureRfcommSocketToServiceRecord.close();
createInsecureRfcommSocketToServiceRecord = null;
} catch (IOException e) {
}
}
I'm modify my code with this but i'm a java.lang.NullPointerException...
The fonction doInBackground() is very difficult...
Thank's for your help !
My code modify
protected Object doInBackground(Object[] objArr) {
BluetoothSocket createInsecureRfcommSocketToServiceRecord = null;
IOException e;
Throwable th;
IButton a;
Boolean valueOf;
boolean z = true;
this.jobType = (JobType) objArr[0];
this.sender = (MainActivity) objArr[1];
this.device = (BluetoothDevice) objArr[2];
try {
createInsecureRfcommSocketToServiceRecord =
device.createInsecureRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
try {
createInsecureRfcommSocketToServiceRecord.connect();
} catch (IOException e2) {
Log.e("Bluetooth", e2.getMessage());
Log.e("Bluetooth", "trying fallback");
try {
createInsecureRfcommSocketToServiceRecord = (BluetoothSocket)
this.device.getClass().getMethod("createInsecureRfcommSocket", new Class[]{Integer.TYPE}).invoke(this.device, new Object[]{Integer.valueOf(1)});
} catch (Exception e3) {
Log.e("Bluetooth", e3.getMessage());
}
try {
createInsecureRfcommSocketToServiceRecord.connect();
} catch (IOException e4) {
e2 = e4;
try {
this.error = e2.getMessage();
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e5) {
}
return null;
} catch (Throwable th2) {
th = th2;
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e6) {
}
throw th;
}
}
}
if (this.jobType == JobType.read) {
a = readDevice(createInsecureRfcommSocketToServiceRecord);
try {
createInsecureRfcommSocketToServiceRecord.close();
return a;
} catch (IOException e7) {
return a;
}
} else if (this.jobType == JobType.stopMission) {
a = (IButton) objArr[3];
if (!(stopMission(createInsecureRfcommSocketToServiceRecord) &&
writeDevice(createInsecureRfcommSocketToServiceRecord, a))) {
z = false;
}
valueOf = Boolean.valueOf(z);
try {
createInsecureRfcommSocketToServiceRecord.close();
return valueOf;
} catch (IOException e8) {
return valueOf;
}
} else if (this.jobType == JobType.startMission) {
boolean z2 = writeDevice(createInsecureRfcommSocketToServiceRecord, (IButton) objArr[3]) &&
startMission(createInsecureRfcommSocketToServiceRecord);
valueOf = Boolean.valueOf(z2);
try {
createInsecureRfcommSocketToServiceRecord.close();
return valueOf;
} catch (IOException e9) {
return valueOf;
}
} else {
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e10) {
}
return null;
}
} catch (IOException e11) {
try {
createInsecureRfcommSocketToServiceRecord.close();
} catch (IOException e1) {
e1.printStackTrace();
}
createInsecureRfcommSocketToServiceRecord = null;
return null;
} catch (Throwable th3) {
th = th3;
} finally {
try {
createInsecureRfcommSocketToServiceRecord.close();
createInsecureRfcommSocketToServiceRecord = null;
} catch (IOException e2) {
}
}
return null;
}

connecting to socket over wifi - android

I am trying to use sockets in Android to connect over wifi to some UDP port (some_port) on a machine in my local network whose ip is some_ip.
When I run
socket = new Socket(some_ip, some_port);
I get no message error but the program does not seem to read this line and I can't log the error when surrounding with try/catch.
How can I debug that ?
Edit 1 : here's my try/catch
try{
socket = new Socket(some_ip, some_port);
}
catch(ConnectException e) {
e.printStackTrace();
}
Edit 2 : here's the entire code
private void getUDPData() throws IOException {
class ProcessUPDTask extends AsyncTask<String, Void, Socket> {
private Exception exception;
private Socket socket;
public ProcessUPDTask() throws IOException {
}
private void runThread(){
new Thread() {
public void run() {
Toast.makeText(activity, "Own Message", Toast.LENGTH_LONG).show();
}
}.start();
}
protected Socket doInBackground(String... urls) {
try {
try{
socket = new Socket(some_ip, some_port);
socket.setSoTimeout(1500);
}
catch(IOException e) {
e.printStackTrace();
}
Log.d("TAG","this line is reached");
while(true){
try {
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if( socket!= null){
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataInputStream!= null){
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if( dataOutputStream!= null){
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
this.exception = e;
e.printStackTrace();
return null;
}
}
protected void onPostExecute(Socket socket) {
// TODO: check this.exception
// TODO: do something with the feed
}
}
new ProcessUPDTask().execute();
}
Try this
try {
Socket socket = new Socket(IP_ADDRESS, PORT);
socket.setSoTimeout(1500);
} catch (IOException ex) {
Log.e("Connection Error",String.valueOf(ex));
}
Replace your code with this and wait some seconds(60 sec for now) you can see the error toast..
private void getUDPData() throws IOException {
class ProcessUPDTask extends AsyncTask<String, Void, Socket> {
private Exception exception;
private Socket socket;
public ProcessUPDTask() throws IOException {
}
protected Socket doInBackground(String... urls) {
try {
try {
socket = new Socket("192.168.1.101", 1234);
socket.setSoTimeout(1500);
} catch (IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_LONG).show();
}
});
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, "Reached", Toast.LENGTH_LONG).show();
}
});
while (true) {
try {
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream = new DataOutputStream(socket.getOutputStream());
System.out.println("ip: " + socket.getInetAddress());
System.out.println("message: " + dataInputStream.readUTF());
dataOutputStream.writeUTF("Hello!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataInputStream != null) {
try {
dataInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (dataOutputStream != null) {
try {
dataOutputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
} catch (Exception e) {
this.exception = e;
e.printStackTrace();
return null;
}
}
protected void onPostExecute(Socket socket) {
// TODO: check this.exception
// TODO: do something with the feed
}
}
new ProcessUPDTask().execute();
}
You can configure this and use transData() between connectivity.
private void transData(int sending_msg_int) throws IOException {
String sending_msg = Integer.toString(sending_msg_int);
SocketAddress socketAddress = new InetSocketAddress(ip, Data.Port);
DatagramSocket ds = new DatagramSocket();
byte[] buffer = sending_msg.getBytes();
DatagramPacket dp = new DatagramPacket(buffer, buffer.length,
socketAddress);
ds.send(dp);
ds.close();
}

post image with text to linkedIn from android app

I want to post image from SD Card with text to linkedIn from my android app.
I could share text but image is not sharing.
I tried with following code:
share.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String share = et.getText().toString();
if (null != share && !share.equalsIgnoreCase("")) {
OAuthConsumer consumer = new CommonsHttpOAuthConsumer(Config.LINKEDIN_CONSUMER_KEY, Config.LINKEDIN_CONSUMER_SECRET);
consumer.setTokenWithSecret(accessToken.getToken(), accessToken.getTokenSecret());
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost post = new HttpPost("https://api.linkedin.com/v1/people/~/shares");
try {
consumer.sign(post);
} catch (OAuthMessageSignerException e) {
e.printStackTrace();
} catch (OAuthExpectationFailedException e) {
e.printStackTrace();
} catch (OAuthCommunicationException e) {
e.printStackTrace();
} // here need the consumer for sign in for post the share
post.setHeader("content-type", "text/XML");
byte[] data = null;
try {
ileInputStream fis = new FileInputStream(imgUrl1);
Bitmap bi = BitmapFactory.decodeStream(fis);
ByteArrayOutputStream baos = new ByteArrayOutputStream()
bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
data = baos.toByteArray();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
Log.d("onCreate", "debug error e = " + e.toString());
}
String myEntity = "<share><comment>"+ text +"</comment> <content><submitted-image-url>data</submitted-image-url></content><visibility><code>anyone</code></visibility></share>";
try {
post.setEntity(new StringEntity(myEntity));
org.apache.http.HttpResponse response = httpclient.execute(post);
Toast.makeText(LinkedInSampleActivity.this,
"Shared sucessfully", Toast.LENGTH_SHORT).show();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else {
Toast.makeText(LinkedInSampleActivity.this,
"Please enter the text to share",
Toast.LENGTH_SHORT).show();
}
}
});
}
In linkedIn you can't share the local images.
For that you need to store the images in server and get the url of that image, now you can post the image to linkedIn...
This may help you...

Second connection to Bluetooth device fails in Android

I'm trying to establish a Bluetooth connection in Android 4.4 but the connect method of BluetoothSocket seems to be working strangely. My app can assume the device is already bonded, so I can connect via MAC address. The thing is that it connects perfectly and immediately the first time the device is bonded, but if I relaunch it, the connection isn't established and a timeout occurs. I do this inside a while loop until it connects, but it takes too long for a real solution or it doesn't work at all. Here's a sample of my code:
public class BluetoothManager{
private BluetoothAdapter bluetoothAdapter;
private BluetoothDevice bluetoothDevice;
private BluetoothSocket socket;
private OutputStream output;
private InputStream input;
public BluetoothManager() {
/***************/
/* Constructor */
/***************/
// lock = new Object();
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public boolean turnOnBluetooth() {
/**************************************/
/* Turn on Bluetooth an notify result */
/**************************************/
// check if bluetooth is supported
if (bluetoothAdapter == null) {
return (false);
} else {
// enable Bluetooth if not enabled yet
if (!bluetoothAdapter.isEnabled()) {
bluetoothAdapter.enable();
}
while (!bluetoothAdapter.isEnabled()) {
Log.i("Debug", "Waiting for bluetooth to turn on");
try {
Thread.sleep(500);
} catch (Exception e) {
}
}
return (true);
}
}
public boolean turnOffBluetooth() {
/***************************************/
/* Turn off Bluetooth an notify result */
/***************************************/
// check if bluetooth is supported
if (bluetoothAdapter == null) {
return (false);
} else {
// disable Bluetooth if not enabled yet
if (bluetoothAdapter.isEnabled()) {
bluetoothAdapter.disable();
}
while (bluetoothAdapter.isEnabled()) {
Log.i("Debug
Thread.sleep(500);
} catch (Exception e) {
}
}
return (true);
}
}
public boolean configureBluetooth(String MACaddress) {
/***********************************************************************/
/* Configures to the specified bluetooth device and returns the result */
/***********************************************************************/
Log.i("Debug", "Connecting to Bluetooth Device");
bluetoothDevice = bluetoothAdapter.getRemoteDevice(MACaddress);
return (true);
}
#SuppressLint("NewApi")
public void createSocket() throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
final UUID serialUUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
socket = null;
output = null;
input = null;
Method m = bluetoothDevice.getClass().getMethod("createInsecureRfcommSocket", new Class[] { int.class });
socket = (BluetoothSocket)m.invoke(bluetoothDevice, 1);
}
#SuppressLint("NewApi")
public void connect() throws IOException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
/************************************/
/* Connects to the bluetooth device */
/************************************/
Log.i("Debug", "en connect");
while (!socket.isConnected()) { // we try until the connection is established
try {
socket.connect();
output = socket.getOutputStream();
input = socket.getInputStream();
} catch (IOException e) {
Log.i("Depuración", "Connection not established. Another run : "+e);
try {
Thread.sleep(1000);
} catch (Exception e1) {
}
}
}
}
public void terminateConnection() throws IOException {
Log.i("Debug", "terminating connection");
if(output!=null){
Log.i("Debug", "output!=null - stop streaming");
stopStreaming();
}
try {
Thread.sleep(100);
} catch (Exception e) {
}
if(input!=null){
Log.i("Debug", "input!=null");
input.close();
input=null;
}
if(output!=null){
Log.i("Depuración", "output!=null");
output.close();
output = null;
}
if(socket!=null){
Log.i("Debug", "socket!=null");
socket.close();
socket=null;
}
try {
Thread.sleep(100);
} catch (Exception e) {
}
turnOffBluetooth();
try {
Thread.sleep(100);
} catch (Exception e) {
}
try {
Thread.sleep(100);
} catch (Exception e) {
}
System.gc();
}
If I call this methods from my MainActivity, it works, but only the first time the device is bonded. If I launch the app again I get an exception trying to connect to the device in:
socket.connect();
I suspect it has something to do with the way I terminate the connection, but I can't figure it out. Here's the sequential call of the methods:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bluetoothManager = new BluetoothManager();
try {
bluetoothManager.terminateConnection();
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
bluetoothManager.turnOffBluetooth();
bluetoothManager.turnOnBluetooth();
boolean configured = false;
while (!configured) {
Log.i("Debug", "Configuration Attemp");
configured = bluetoothManager.configureBluetooth(MACaddress);
}
Log.i("Debug", "Bluetooth Configured");
try {
bluetoothManager.createSocket();
} catch (NoSuchMethodException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Log.i("Depuración", "Socket created");
try {
bluetoothManager.connect();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i("Debug", "Connected!!!!");
protected void onPause() {
Log.i("Debug", "On pause");
// TODO Auto-generated method stub
try {
bluetoothManager.terminateConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bluetoothManager = null;
System.gc();
super.onPause();
};
I've been trying to solve this for days and I still can't find a reason.
Well I'm not a Pro on this, but it looks like you should call bluetoothManager.terminateConnection(); when app is closing, lets say onDestroy, but not onCreate; I also had problems to connect, if previous connection was not terminated correctly. just try add this method to your main activity:
#Override
public void onDestroy(){
if (bluetoothManager != null){
bluetoothManager.terminateConnection();
}
super.onDestroy();
}
hope that helps.

How to get the new data update from a json url in android?

I am working in an online radio streaming project. I play the stream from a url and parsing the sound track info from another json url. All that I did is I repeatedly parse the json after every 10 seconds thats why when the sound track is changing I can get the track info of that specific track. But the json file is being updated 30+ sec before the track changes, thats why sometimes there is a noticeable dissimilarity between the track and the track info.
Here is my asyncTask class where I am playing the stream.
public class RadioPlayer extends AsyncTask<String, Void, Void> {
MediaPlayer mediaPlayer = new MediaPlayer();
#Override
protected void onPreExecute() {
}
#Override
protected Void doInBackground(String... params) {
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(params[0]);
mediaPlayer.prepare();
} catch (IllegalArgumentException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalStateException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// might take long! (for buffering, etc)
mediaPlayer.start();
return null;
}
#Override
protected void onPostExecute(Void result) {
}
and here is the handler where I am updating the track info after every 10 seconds:
private void getSongStatistics() {
r = new Runnable() {
public void run() {
try {
title = tsp.parseInitiator();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
Log.i("title", title);
try {
String[] subTitles = title.split("-");
tvTitle.setText(subTitles[1]);
tvArtist.setText(subTitles[0]);
} catch (Exception e) {
tvArtist.setText(title);
}
handler.postDelayed(this, 10000);
}
}
};
handler.postDelayed(r, 10000);
}
Is there any solution by which I may get rid of this weird problem?
Use push instead of polling to update data.

Categories

Resources