I'm doing an Android application that will make some requests to an API, I generalized these requests in a class (RequestApi), where to use it, it would be enough to create a map with the information that I will send to API and call as follows:
new RequestApi(activity, url, mapa_com_as_variaveis).exec();
//o retorno dessa requisição serão um JSONObject com a resposta do servidor
This works, but I'm trying to put a loading icon while the request is being performed (the user can only take any action after the server response, that is, it is a synchronous request).
package br.com.david.system.Utils;
import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewManager;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;
import br.com.david.system.Database.MaquinaHelper;
import br.com.david.system.PrincipalActivity;
import br.com.david.system.R;
public class RequestApi {
public static final String BASE_URL = "http://myapi.com.br/api/";
private String url;
private String json;
private String message;
private String request;
private JSONObject response;
private Activity activity;
public RequestApi(Activity a, String url, Map<String, Object> data) {
this.activity = a;
this.url = url;
setCrypt(data); //criptografo os dados que serão enviados pra API
}
public JSONObject exec(){
init(); //inicio o carregamento (ícone loading)
Log.e("JSON_SEND", json);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
try {
//
URLConnection conn = new URL(url).openConnection();
conn.setDoOutput(true);
conn.setConnectTimeout(15000);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = conn.getOutputStream();
os.write(json.getBytes("UTF-8"));
os.flush();
InputStream in = new BufferedInputStream(conn.getInputStream());
request = convertStreamToString(in);
in.close();
os.close();
if (request != null) {
Log.e("RESPONSE", "response: " + request.toString());
try {
response = new JSONObject(request);
if (response.getInt("error_code") == 0) {
if (response.get("data") instanceof JSONObject) {
JSONObject dataResponse = response.getJSONObject("data");
if (dataResponse.has("x-auth-token")) {
//verifico os tokens do cabeçalho
}
}
} else {
message = response.getString("message");
Log.e("URL", "url: " + url);
}
} catch (final JSONException e) {
message = "Não foi possível obter a resposta do servidor";
Log.e("ERROR", "json_error: " + e.getMessage());
}
} else {
message = "Não foi possível conectar-se ao servidor";
}
} catch (Exception e){
Log.e("Exception", "err -> " + e.getMessage());
}
}
});
thread.start();
Log.e("THREAD", "start()");
try {
thread.join();
Log.e("THREAD", "end()");
abort();
Log.e("REPS", "Response: " + response.toString());
return response;
} catch (InterruptedException e) {
e.printStackTrace();
Log.e("THREAD", e.getMessage());
return null;
}
}
private void setCrypt(Map<String, Object> data){
for(Map.Entry<String, Object> entry : data.entrySet()) {
//criptografo os dados do mapa
}
json = new JSONObject(data).toString();
}
public void init(){ //open loading
ViewGroup frameLayout = activity.findViewById(R.id.flContent);
LayoutInflater inflater = (LayoutInflater) activity.getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myView = inflater.inflate(R.layout.loading, null);
if(frameLayout != null){
frameLayout.addView(myView);
}
}
protected void abort() { //close loading
ViewGroup group = (ViewGroup) activity.findViewById(R.id.loading);
((ViewManager) group.getParent()).removeView(group);
}
/*
* To convert the InputStream to String we use the
* Reader.read(char[] buffer) method. We iterate until the
* Reader return -1 which means there's no more data to
* read. We use the StringWriter class to produce the string.
*/
public String convertStreamToString(InputStream is) throws IOException {
if (is != null) {
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} finally {
is.close();
}
return writer.toString();
} else {
return "";
}
}
}
I have already tried in DIFFERENT ways to make the loading screen appear (it is an external file, R.layout.loading ), among them:
- Pure code: An error occurred stating that I could not execute requests on the main thread;
- AsyncTask: The icon appeared only after the request was completed (I placed the code that started the icon in onPreExecute, before the AsyncTask call and even in several places of the code;
- Thread: It's the example below, it works the same way as with AsyncTask, the icon is displayed only after the request is completed;
- Handler.post and Handler.postDelayed: Same thing as Thread and AsyncTask;
- For all cases I tried to put the opening of the icon in runOnUIThread and with Handlers, I tried in many other ways too (things I knew did not make sense).
I no longer have any options, can anyone help me? (the loading icon is a layout with a RelativeLayout - background almost transparent catching the entire screen - and a ProgressBar, all screens have a FrameLayout with ID = flContent).