Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firestore timeout for android

I am currently building an app that saves the user's blog post in Firestore server. Everything is working fine, but I found out that the post was not uploaded under the unstable internet connection.

I tried to set a timeout to the Firestore instance, but it seems like there's no timeout option for Firestore library. The problem is, because there's no timeout setting, the app doesn't know when to dismiss the uploading screen (Spinner dialog).

I was thinking about creating a Handler or Observable or Thread and setting the timeout manually. After the specified timeout period, let the app dismiss the uploading screen. However, Firestore client will keep retrying the upload in the background even after the timeout. So this approach won't be suitable for this case...

Is there any solution for this? If I can set the timeout for the Firestore client itself, meaning letting the client to call onFailure() after the given timeout period, I can just save the post as draft in the local storage and try it again when the device is back to stable connection.

like image 887
WasabiTea Avatar asked May 29 '18 22:05

WasabiTea


2 Answers

Firestore will immediately add the document to its local cache. It will then try to synchronize that document with the server. To detect whether it will be able to do so, have a look at Gastón's answer.

To detect when the document has been written to the server, use a SuccessListener. This example from the Firestore documentation on adding documents shows how:

// Add a new document with a generated id.
Map<String, Object> data = new HashMap<>();
data.put("name", "Tokyo");
data.put("country", "Japan");

db.collection("cities")
        .add(data)
        .addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
            @Override
            public void onSuccess(DocumentReference documentReference) {
                Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.getId());
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Log.w(TAG, "Error adding document", e);
            }
        });
like image 151
Frank van Puffelen Avatar answered Oct 03 '22 11:10

Frank van Puffelen


The best way of doing this is attaching a boolean that will let you know if you have internet before doing something (this is just to dismiss your spinner, as firestore has offline features like realtime database)

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}

so you should check first if you have an active connection , this method will ping google.com and check for internet connection, if is not reachable after 1.5 seconds it will return false

so you should do something like this (pseudocode)

if(hasActiveInternetConnection)
doyourfirebaseuploadstuff
else
spinner.dismiss()
Toast(please check your internet connection and try again)

Remember to add your internet permissions in your manifest

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

EDIT:

Another cool method and maybe more readable for someones can be this one

public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

it just works like the other one , instead that this will just wait for 10 seconds untill it returns the internet status

like image 25
Gastón Saillén Avatar answered Oct 03 '22 09:10

Gastón Saillén