Cómo usar AsynTask en un proyecto Android

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.

Tendremos que tener los siguientes dos permisos configurados:

Petición GET con AsynTask

new MiAsyncTask().execute("https://pablomonteserin.com/curso/php/res/leer-valor.php");
//El primer parámetro es lo que recibe doInBackground
//El segundo parámetro es lo que recibe un método que no estamos utilizando
//El tercer parámetro es lo que devuelve doInBackground (una cookie es un String)

private class MiAsyncTask extends AsyncTask<String, Integer, String> {
	//doInBackground es un método que se ejecuta en el background. 
	//Aquí realizamos operaciones pesadas que pueden durar mucho tiempo dando lugar a una excepción
	//doInBackground no debe tocar nada de la interfaz visual. Estas operaciones serán hechas en onPostExecute
	protected String doInBackground(String... urls) {
		URL url = new URL(urls[0]);
		URLConnection urlConnection = url.openConnection();
		BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
		String line;
		while ((line = bufferedReader.readLine()) != null){
			content.append(line + "\n");
		}
		bufferedReader.close();
		return content.toString();
	}

	//El método onPostExecute debe recibir lo que devuelve el doInBackground (en este caso, un String)
	protected void onPostExecute(String txt) {
	}
}

Ejercicio: petición GET con AsynTask

El código UPC que escribimos se lo mandaremos a la url

Para probar podremos utilizar el código:
upcCode=1234

Usaremos el permiso:

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

Petición POST con AsyncTask

public class AsynTaskPorPOST extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.asyntask_post);
}

public void hacerPeticion(View v){
	new MiAsyncTask().execute("https://pablomonteserin.com/curso/php/res/peticion-post-android.php","option=3");
}

private class MiAsyncTask extends AsyncTask<String, Integer, String> {

	protected String doInBackground(String... params) {
		StringBuilder content = new StringBuilder();

		try
		{
			URL url = new URL(params[0]);

			HttpURLConnection connection = (HttpURLConnection) url.openConnection();

			connection.setRequestMethod("POST");
			connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			connection.setRequestProperty("Accept", "*/*");

			connection.setDoOutput(true);
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
			writer.write(params[1]);
			writer.close();
			connection.connect();

			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line;
			while ((line = bufferedReader.readLine()) != null)
			{
				content.append(line + "\n");
			}
			bufferedReader.close();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
		return content.toString();
	}
	protected void onPostExecute(String txt) {
//El método onPostExecute debe recibir lo que devuelve el doInBackground (en este caso, un String)
		Toast.makeText(AsynTaskPorPOST.this, txt,Toast.LENGTH_SHORT).show();
	}
}
}

Procesar un JSON

Si quiero acceder a elementos de un array, usaré, JSONArray, y si quiero acceder a propiedades de un objeto, usaré JSONObject

JSONObject jObject = jObject = new JSONObject(respuesta);
JSONArray jArray = jObject.getJSONArray("results");
ArrayList<String> lista = new ArrayList<String>();
for (int i=0;i<jArray.length();i++) {
	String valor = jArray.get(i).toString();
	JSONObject jObject2 = new JSONObject(valor);
	lista.add(jObject2.getString("name"));
}

Petición GET con Retrofit

Debemos importar las librerías de Retrofit

build.gradle (module)
// Retrofit
api 'com.squareup.retrofit2:retrofit:2.3.0'
api 'com.squareup.retrofit2:converter-gson:2.3.0'
public class GetRequest extends AppCompatActivity{
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_get_request);
	}

	public void hacerPeticion(View v){
		Retrofit builder = new Retrofit.Builder()
			.baseUrl("https://swapi.co/api/")
			.addConverterFactory(GsonConverterFactory.create())
			.build();

		PabloAPI api = builder.create(PabloAPI.class);
		api.peticionGET().enqueue(new Callback<ResponseBody>() {
		
		@Override
		public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
			try {
				String respuesta = response.body().string();
				Log.d("RESPUESTA", respuesta);
				Toast.makeText(getBaseContext(), respuesta, Toast.LENGTH_LONG).show();
				// Procesamos el resultado de la petición...
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		@Override
		public void onFailure(Call<ResponseBody> call, Throwable t) {
			Toast.makeText(GetRequestSimplificada.this, "Error", Toast.LENGTH_SHORT).show();
		}
	});
}
}
public interface PabloAPI {
	@GET("people/")
	Call<ResponseBody> peticionGET();
}

Petición POST con Retrofit

El código es muy parecido al de la petición GET, pero cambiando el fichero API:

PabloMonteserinAPI.java
public interface PabloMonteserinAPI {
	//Las cabeceras deben estar en consonancia con el tipo de dato que vamos a recuperar u obtendremos un error 406
	//  @Headers({"Accept: application/json"})
	@Headers({"Accept: text/html"})
	@FormUrlEncoded
	@POST("curso/php/res/peticion-post-android-2.php/")
	Call<ResponseBody> peticionPOST(@Field("nombre") String nombre, @Field("apellidos") String apellidos);
}
@Headers({"Accept: text/html"})
@POST("users/login")
Call<ResponseBody> login(@Body User user); 
//api.peticionPOST("Pablo", "Monteserrín").enqueue(new Callback<ResponseBody>() {
	...

Subida de una imagen de la galería al servidor con Retrofit

Nesitaremos los siguientes permisos en el manifest:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SubidaImagen.java
public class SubirImagen extends AppCompatActivity {

	private boolean isAndroid6;
	private final int MY_PERMISSIONS_REQUEST_CAMARA = 1;

	TextView image_name_tv;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_subir_imagen);
		image_name_tv = findViewById(R.id.nombreFoto);

		if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
			isAndroid6 = true;
			askPermissionsIfneeded();
		}
	}
	private void askPermissionsIfneeded(){
		if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
			ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_CAMARA);
		}
	}

	@Override
	public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
		switch (requestCode) {
			case MY_PERMISSIONS_REQUEST_CAMARA: {
			// If request is cancelled, the result arrays are empty.	
				if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
					// permission was granted, yay! Do the
					// contacts-related task you need to do.
				}else {
					// permission denied, boo! Disable the
					// functionality that depends on this permission.
				}
				return;
			}
            // other 'case' lines to check for other
            	// permissions this app might request
		}
	}

    public void sacarFoto(View v){
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, 1);

        /*Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        	if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
        	    startActivityForResult(takePictureIntent, 1);
        	}*/
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 1)
            if (resultCode == Activity.RESULT_OK) {
                Uri selectedImage = data.getData();

                String filePath = getPath(selectedImage);
                String file_extn = filePath.substring(filePath.lastIndexOf(".") + 1);
                image_name_tv.setText(filePath);

                if (file_extn.equals("img") || file_extn.equals("jpg") || file_extn.equals("jpeg") || file_extn.equals("gif") || file_extn.equals("png")) {
                    File file = new File(filePath);
                    RequestBody requestFile =
                            RequestBody.create(
                                    MediaType.parse(getContentResolver().getType(selectedImage)),
                                    file
                            );
                    MultipartBody.Part body =
                            MultipartBody.Part.createFormData("sampleFile", file.getName(), requestFile);
                    String descriptionString = "hello, this is description speaking";
                    RequestBody description =
                            RequestBody.create(
                                    okhttp3.MultipartBody.FORM, descriptionString);
                    RetrofitService retrofitService = RetrofitService.getInstance();
                    PabloAPI api = retrofitService.getApiProxyServer();
                    api.uploadFile(description,body).enqueue(new Callback<ResponseBody>() {
                        @Override
                        public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                            Toast.makeText(SubirImagen.this, "Imagen subida", Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onFailure(Call<ResponseBody> call, Throwable t) {
                            Toast.makeText(SubirImagen.this, "Error", Toast.LENGTH_SHORT).show();
                        }
                    });

                } else {
                    //NOT IN REQUIRED FORMAT
                }
            }
    }

    public String getPath(Uri uri) {
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri,filePathColumn, null, null, null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        return picturePath;
    }
}
PabloAPI
public interface PabloAPI {
    @Multipart
    @POST("subida/upload")
    Call<ResponseBody> uploadFile(@Part("description") RequestBody description, @Part MultipartBody.Part file);
}
public class RetrofitService {
	private static RetrofitService INSTANCE = null;
	private static final String BASE_URL = "http://pablomonteserin.com:19139";
	private PabloAPI apiService;

	// Private constructor suppresses    
	private RetrofitService(){
		Retrofit builder = new Retrofit.Builder()
			.baseUrl(BASE_URL)
			.addConverterFactory(GsonConverterFactory.create())
			.build();

		apiService = builder.create(PabloAPI.class);
	}

	// creador sincronizado para protegerse de posibles problemas  multi-hilo
	// otra prueba para evitar instanciación múltiple
	private synchronized static void createInstance() {
		if (INSTANCE == null) {
			INSTANCE = new RetrofitService();
		}
	}

	public static RetrofitService getInstance() {
		if (INSTANCE == null) createInstance();
		return INSTANCE;
	}

	public PabloAPI getApiProxyServer(){
		return apiService;
	}
}
Servidor nodejs con Express
router.post('/upload', function(req, res) {
  console.log(req.files);
  console.log("amor");
  if (!req.files)
    return res.status(400).send('No files were uploaded.');
  // The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
  let sampleFile = req.files.sampleFile;
 
  // Use the mv() method to place the file somewhere on your server
  sampleFile.mv('/usr/home/pablomonteserin/termine/public/subida/filename.jpg', function(err) {
    var path = require("path");
      console.log("./ = %s", path.resolve("./"));
      console.log("__dirname = %s", path.resolve(__dirname));

    if (err){
      console.log("adasda")
      return res.status(500).send(err);
    }
    res.send('File uploaded!');
  });
});

router.get('/', function(req, res){
	res.write(`<html>
	<body>
	<form ref='uploadForm' 
		id='uploadForm' 
		action='http://pablomonteserin.com:19139/subida/upload' 
		method='post' 
		encType="multipart/form-data">
		<input type="file" name="sampleFile" />
		<input type='submit' value='Upload!' />
		</form>     
		</body>
	</html>`);
  	res.end();
});
app.js
const fileUpload = require('express-fileupload');
app.use(fileUpload());

Por 9.99€ al mes tendrás acceso completo a todos los cursos. Sin matrícula ni permanencia.