0
I’m making an Android application that will make some requests to an API, I generalized these requests in a class (Requestapi), where, to use it, just create a map with the information I’ll send to the API and call in the following way:
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 am trying to put a loading icon while the request is being performed (the user can only perform any action after the server response, ie 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 tried SEVERAL 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 in the Main Thread;
- Asynctask: The icon appeared only after the request ended (I put the code that started the icon in onPreExecute, before the Asynctask call and even in various places of the code;
- Thread: As an example below, it works the same way with Asynctask, the icon is only displayed after the request is completed;
- Handler.post and Handler.postDelayed: Same as Thread and Asynctask;
- For all cases I tried to put the icon opening in runOnUIThread and with Handlers, I tried several other ways too (things I knew didn’t make any sense).
I’m out of options, can someone help me? (the loading icon is a layout with a Relativelayout - almost transparent background grabbing the entire screen - and a Progressbar, all screens have a Framelayout with ID = flContent).