Android Offline Request with Volley
Asked Answered
F

3

17

I want to give to my user a much better offline user experience, therefore, I want to build a Service which stores all POST, DELETE, PUT (GET makes no sense because a GET call without network is a cache call) requests the user does offline and send them to the server as soon as the user got an internet connection. I want it to be persistent: even if the app is killed, data are sent in order not to have inconstancies between cache and server data.

I'm quite familiar with Google Volley and Android Networking API --> I know how to detect there is no network, how to prefetch data, to cache them etc...

But is there a gist or a library about this subject? I know that the latest Facebook version implements such a system but I wonder how they did (I mean, I know there're using a Service but how they exactly did, got no idea!). Does someone has idea on that, any experience?

Fullblown answered 25/7, 2015 at 15:24 Comment(8)
About persistant service, have you read this question yetLorenza
Yes, I did but I want to know if there something a bit less generic :)Fullblown
You can look into RobospiceRetrofit library... It uses Services to send request to server and u can get data from cache if the app is offline. But I think the Service is destroyed when you exit the app. Hope it helps...Landa
Have you looked for SyncAdapter developer.android.com/training/sync-adapters/… ?Geilich
That could do the job, that's true, seems to be overkill but at the end, it's maybe the best approachFullblown
👍 for retrofit. You're looking to build a cache and that's by far the easiest and best bet.Erasme
Hi, which way did you go finally?Considering
@Considering Didn't go any way yet, I save the action in a json file and send these actions when I'm back online. Nevertheless, I'm not satisfied with it yet.Fullblown
W
5

You need to use a BroadcastReceiver to listen to network change events. Define a broadcastReciver in your AndroidManifest.xml with the following action.

<receiver android:name=".NetworkBroadcastReceiver" >
     <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
     </intent-filter>
</receiver>

Also add the following permissions as well to your manifest file -

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

NetworkBroadcastReceiver -

public class NetworkBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {

        if(isInternetConnected(context)) {
            //Do something i.e. trigger an API call or start a IntentService etc.
        }    
    }


    public boolean isInternetConnected(Context context) {
        ConnectivityManager connectivityManager 
            = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }    
}

That's all you need to do to make a request as soon as you get Internet.

To cache data, I'll advise you to parse the server response and keep it in your database for offline use. Every time you make a successful request save the new data in database and discard the old one. When user starts the app, load the data from database first and then trigger the Volley request, if request become successful then load the new data in app, store it in database and get rid of the old one. So in case if request fails, user will still be able to see the old data from previous successful request.

To handle inconsistency between data in app and server, you need to use SyncAdapter. SyncAdapter provide a great support for periodic sync in the background. Just put the syncing code in onPerformSync() method of SyncAdapter. It might not work in following two scenarios - 1. If user isn't connected to internet 2. If user device is turned off

To handle these scenario, use the BroadCastReceiver that I explained above in my answer to trigger the SyncAdapter. Also add the following actions to your receiver inside AndroidManifest.xml to listen to boot complete event of device.

<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />

Let me know if you need more in depth explanation with coding example. Hope it helps

Wolfort answered 16/9, 2015 at 1:7 Comment(0)
C
3

Take a look at this library that I came across - Android Priority Job Queue.

You define your background tasks as Jobs and enqueue them to your JobManager instance. Job Manager will take care of prioritization, persistence, load balancing, delaying, network control, grouping etc. It also provides a nice lifecycle for your jobs to provide a better, consistent user experience.

Also, they monitor network connectivity. When a device is offline, jobs that require network connection won't run until network connectivity is restored.

Considering answered 11/4, 2016 at 9:31 Comment(1)
I see, I will give a look because I almost write this lib for this need... #stupid Thx mateFullblown
P
0

you maybe do a networking validation method :
1. check the network connection
YES:
a) make the volley request
b) parse the adapter from volley request
c) and save the json into a private file

NO:
a) read the private file
b) make the adapter from json file downloaded.

********************** for example

    if(isconnect){   
    JsonArrayRequest Req = new JsonArrayRequest(url,
            new Response.Listener<JSONArray>() {
                public void onResponse(JSONArray response) {
                  //this the request of your http request 
                   Log.d(TAG, response.toString());
                     // Parsing json
                      for (int i = 0; i < response.length(); i++) {
                        try {
                         ......adapter etc etc
                         }
                        adapter.notifyDataSetChanged();
                        //here write the httprequest (json file) in local memory 
                          try {
                          String textjson= response.toString();
                          fos = context.openFileOutput("request.json",MODE_PRIVATE);
                          fos.write(textjson.getBytes("ISO-8859-1")); //encode
                          fos.close();
                          } catch (IOException e) {
                             // TODO Auto-generated catch block
                             e.printStackTrace();
                          }
                    swipeRefreshLayout.setRefreshing(false);  
                 }  
              }, new Response.ErrorListener() {
               @Override
               public void onErrorResponse(VolleyError error) {
               // VolleyLog.d(TAG, "Error: " + error.getMessage());
             }   });      AppController.getInstance().addToRequestQueue(movieReq);
                            }
                        else{
                            //noconnection();
                            in the noconnection method u can parse the               listview/recyclerview from json file to make the offline mode } 
}else{
    //parse the listview/recyclerview from local file. }
Plumlee answered 15/9, 2015 at 17:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.