Curso de Android | Cómo usar AsynTask 1

Curso de Android
Cómo usar AsynTask

Curso de Android | Cómo usar AsynTask 2

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:

https://pablomonteserin.com/res/php/res/miupcsearch.php?upc_code=1234

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 = "https://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='https://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());