0

The task is simple, but I want to do it in the right way and I would love to hear your expert advice because I am novice in android developing.

First the application is just for me so I really don't care about security and stuff.

So my objective is like this:

I have a large amount of data that I want to transfer to my MYSQL database, the easiest way for me is to use HTTP POST method, but I am concerned about the part that the application may get stuck or some data won't pass because of the many POST requests that are gonna be.

So how exactly should I pass the data using POST request with insuring that all of the requests will be sent one by one without skipping any or losing data ?

Just the logic behind this would be enough I don't really need the code part. Hopefully I was clear enough.

  • 1
    Lookup AsyncTask and rest client for android . – Jimmy Apr 18 '18 at 15:56
  • To use quickly with maintainable and flexible code use a Network library . See [This](https://stackoverflow.com/questions/16902716/comparison-of-android-networking-libraries-okhttp-retrofit-and-volley). You can use any of it. – ADM Apr 18 '18 at 15:57
  • You could use Android library Fast-Android-Networking https://github.com/amitshekhariitbhu/Fast-Android-Networking – Prashant Abdare Apr 18 '18 at 16:00
  • 1
    @ADM how you put link, See "this" in your comment, is it or something else? – Prashant Abdare Apr 18 '18 at 16:04
  • 1
    @Prashant https://meta.stackexchange.com/questions/61071/adding-links-to-comments. Just search what you need Everything listed on https://meta.stackexchange.com. You might find [This one](https://meta.stackexchange.com/questions/92060/add-data-se-style-magic-links-to-comments) interesting . – ADM Apr 18 '18 at 16:05
  • @ADM VERY nice library but can I rest a sure that it will do the work for me or I still need to use AsyncTask method ? – Daniel Iliaguev Harta Apr 18 '18 at 16:07
  • Network libraries are well maintained for multi-threaded environment. You can go with it . I myself suggest `RetroFit`. – ADM Apr 18 '18 at 16:12

2 Answers2

1

Retrofit FTW. Makes networking easy on Android (RESTful) and it include Gson. Speaking of Gson... You mention you might be making many POSTs? If so, you should probably convert your data to JSON instead, and send it over the network that way. Google's Gson is a fantastic way to easily convert a Java object to JSON. http://square.github.io/retrofit/ https://github.com/google/gson

0

Before reading: this is my way for implementing posts and gets, this is not the best way ever, but just the best way for my needs, feel free to edit/not use/implement it yourself

I personally prefer OkHTTP library, it is easy to use and easy to implement.

Implementation is really easy, just add this row in your Gradle app-level

implementation 'com.squareup.okhttp3:okhttp:3.9.0'

Then I created an helper class for get and post calls (I don't need many configurations, so a static one for me was enough, if you need more stuff you can easily implement. Also the timeouts are set for my needs and you can chenge them freely)

private String ConsumeGetRequest(String path) {
    int tries = 0;
    boolean isMyException = true;
    while (tries <= 3 && isMyException) {
        try {
            isMyException = false;
            tries++;
            Response response = executeRequestBody(path, null);
            if (response != null && response.body() != null)
                return response.body().string();
            else
                return "";

        } catch (ConnectException e) {
            e.printStackTrace();
            if (e.getMessage().contains("Failed to connect to") && tries <= 3) {
                isMyException = true;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            return "";
        }
    }
    return "";
}

private Pair<Boolean, String> ConsumePostRequest(String path, String postData) {
    int tries = 0;
    String errorMsg = null;
    boolean isMyException = true;
    //you can ignore this while, it was for our internal reasons and it's just a check.
    while (tries <= 3 && isMyException) {
        try {
            isMyException = false;
            tries++;
            Response response = executeRequestBody(path, postData);
            if (response != null && response.body() != null)
                return new Pair<>(response.isSuccessful(), response.body().string());
            else
                return new Pair<>(false, null);
        } catch (ConnectException e) {
            errorMsg = e.getMessage();
            if (e.getMessage().contains("Failed to connect to") && tries <= 3) {
                isMyException = true;
            }
        } catch (Exception ex) {
            errorMsg = ex.getMessage();
        }
    }
    return new Pair<>(false, errorMsg);
}

private Response executeRequestBody(String path, String postData) throws IOException {
    String url = String.format("%s%s/", RuntimeHelper._baseWebServiceIP, path);
    if (okHttpClient == null) {
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(120, TimeUnit.SECONDS)
                .readTimeout(120, TimeUnit.SECONDS)
                .build();
    }
    Request.Builder builder = new Request.Builder().url(url);
    if (postData != null && !postData.isEmpty()) {
        RequestBody body = RequestBody.create(RuntimeHelper._okHttpTypeJson, postData);
        builder = builder.post(body);
    }
    Request request = builder.build();

    return okHttpClient.newCall(request).execute();
}

with those two methods (a couple of examples) I create my path and I call the proper method for my needs.

//Post
    public boolean setAlerts(String postData) {
        String path = String.format("api/wfm/v1/set-alerts/%s/%s", authToken, resourceId);
        return ConsumePostRequest(path, postData).first;
    }

    //Post
    public String isAlertUpdated(String lastDownloadDate) {
        String path = String.format("api/wfm/v1/is-alert-updated/%s/%s", authToken, lastDownloadDate);
        return ConsumeGetRequest(path);
    }

Then with an AsyncTask you can perform the operation without blocking UI

public class NewAlertAsyncTask extends AsyncTask<String, String, Boolean> {

    Context context;

    private WebApiMethodsController webApiMethodsController;
    AuthenticatedUser authenticatedUser;

    public NewAlertAsyncTask(Context ctx) {
        this.context = ctx;
        authenticatedUser = AuthenticatedUser.getIstance(context);
        webApiMethodsController = new WebApiMethodsController(authenticatedUser.getAuthenticationTokenID().toString(), authenticatedUser.getResourceID().toString(), context);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(String... values) {
    }

    @Override
    protected Boolean doInBackground(String... datas) {
        Boolean result;
        try {
            result = webApiMethodsController.setAlerts(datas[0]);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return result;
    }

    @Override
    protected void onPostExecute(Boolean s) {
        if(s){
            //manage succes, I use this
            mCallback.onNewAlertCreated();
        }
        else{
            //manage error
        }
    }
}

mine is a really simple structure, you can implement it with callbacks, status progress, deeper return status check, ...

You can simply call the asynctask with this

            NewAlertAsyncTask newAlertAsyncTask = new NewAlertAsyncTask(getActivity());
            newAlertAsyncTask.execute(gson.toJson(alertList));
Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66