Servicios en Android

Uso de servicios

Servicios en Android (Servicios)

Descripción general de los servicios

Servicios en Android:

Un servicio en segundo plano:

La diferencia entre IntentService y Service

Service versus IntentService

Introducción a los servicios (ejemplo: Un servicio en segundo plano)

Ejemplo: Crear un servicio para reproducir música

Código del Servicio Reproductor de Música

Ejemplo: Crear un servicio para descargar un fichero en segundo plano

build.gradle:

dependencies {



    implementation("com.squareup.okhttp3:okhttp:4.12.0")
}

permisos en el manifiesto:

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

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Descarga de fichero"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.044" />

    <Switch
        android:id="@+id/switch1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="IntentService"
        app:layout_constraintBottom_toTopOf="@+id/botonIniciar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.919"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView"
        app:layout_constraintVertical_bias="1.0" />

    <Button
        android:id="@+id/botonIniciar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="36dp"
        android:text="Iniciar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.528"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <Button
        android:id="@+id/botonParar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Parar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.534"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/botonIniciar"
        app:layout_constraintVertical_bias="0.0" />

    <TextView
        android:id="@+id/salida"
        android:layout_width="260dp"
        android:layout_height="126dp"
        android:layout_marginTop="44dp"
        android:text="resultado de la descarga"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.582"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/botonParar"
        app:layout_constraintVertical_bias="0.0" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public ActivityMainBinding binding;
    private static final int REQUEST_CONNECT = 1;
    public static final String WEB = "https://dam.org.es/ficheros/frases.html";
    public static final String ACTION_RESP = "RESPUESTA_DESCARGA";
    IntentFilter intentFilter;
    BroadcastReceiver broadcastReceiver;

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

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        binding.botonIniciar.setOnClickListener(this);
        binding.botonParar.setOnClickListener(this);

        intentFilter = new IntentFilter(ACTION_RESP);
        intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
        broadcastReceiver = new ReceptorOperacion();
        // registerReceiver(broadcastReceiver, intentFilter);
    }

    @Override
    public void onResume(){
        super.onResume();
        //---registrar el receptor ---
        registerReceiver(broadcastReceiver, intentFilter);
    }

    @Override
    public void onPause(){
        super.onPause();
        //--- anular el registro del recpetor ---
        unregisterReceiver(broadcastReceiver);
    }

    public class ReceptorOperacion extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String respuesta = intent.getStringExtra("resultado");
            binding.salida.setText(respuesta);
            // mostrarMensaje(respuesta);
        }
    }

    @Override
    public void onClick(View v) {

        binding.salida.setText("");

        if (v == binding.botonIniciar) {
            if (comprobarPermiso()) {
                if (!binding.switch1.isChecked()) {
                    // uso con Service
                    startService(new Intent(MainActivity.this, DownloadService.class));
                } else {
                    // uso con IntentService
                    Intent i = new Intent(this, DownloadIntentService.class);
                    i.putExtra("web", WEB);
                    startService(i);
                }
            }
        }

        if (v == binding.botonParar) {
            if (!binding.switch1.isChecked()) {
                stopService(new Intent(MainActivity.this, DownloadService.class));
            } else {
                stopService(new Intent(MainActivity.this, DownloadIntentService.class));
            }
        }
    }

    private boolean comprobarPermiso() {
        //https://developer.android.com/training/permissions/requesting?hl=es-419
        String permiso = Manifest.permission.WRITE_EXTERNAL_STORAGE;

        boolean concedido = false;
        // comprobar los permisos
        if (ActivityCompat.checkSelfPermission(this, permiso) != PackageManager.PERMISSION_GRANTED) {
            // pedir los permisos necesarios, porque no están concedidos
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, permiso)) {
                concedido = false;
            } else {
                ActivityCompat.requestPermissions(this, new String[]{permiso}, REQUEST_CONNECT);
                // Cuando se cierre el cuadro de diálogo se ejecutará onRequestPermissionsResult
            }
        } else {
            concedido = true;
        }
        return concedido;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        String permiso = Manifest.permission.WRITE_EXTERNAL_STORAGE;
        //Manifest.permission.INTERNET;
        // chequeo los permisos de nuevo
        if (requestCode == REQUEST_CONNECT)
            if (ActivityCompat.checkSelfPermission(this, permiso) == PackageManager.PERMISSION_GRANTED)
                // permiso concedido
                startService(new Intent(MainActivity.this, DownloadService.class));
            else
                // no hay permiso
                mostrarError("No se ha concedido permiso para escribir en memoria externa");
    }

    private void mostrarError(String mensaje) {
        Toast.makeText(this, mensaje, Toast.LENGTH_SHORT).show();
    }

}

Comprobar permiso para escribir en memoria

Descarga del archivo

Escribir en memoria externa el fichero descargado

DownloadService.java

public class DownloadService extends Service {

    public static final String WEB = "https://dam.org.es/fichero/frases.html";

    public DownloadService() {
    }
 
    @Override public void onCreate() { 
        super.onCreate();
        mostrarMensaje("Creando el servicio . . .");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        URL url = null;
        try {
            url = new URL(WEB);
            descargaOkHTTP(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            mostrarMensaje("Error en la URL: " + WEB);
        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mostrarMensaje("Servicio destruido");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    private void descargaOkHTTP(URL web) {
        final OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
                .url(web)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                Log.e("Error: ", e.getMessage());
            }

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException{
                try (ResponseBody responseBody = response.body()) {
                    if (!response.isSuccessful()) {
                        //throw new IOException("Unexpected code " + response);
                        Log.e("Error: ", "Unexpected code " + response);
                    } else {
                        // Read data on the worker thread
                        final String responseData = response.body().string();
                        // guardar el fichero descargado en memoria externa
                        if (escribirExterna(responseData)) {
                            Log.i("Descarga: ", "fichero descargado");
                        } else
                            Log.e("Error ", "no se ha podido descargar");
                    }
                }
            }
        });
    }

    private void mostrarMensaje(String mensaje) {
        Toast.makeText(this,mensaje, Toast.LENGTH_SHORT).show();
    }

    private boolean escribirExterna(String cadena) {
        File miFichero, tarjeta;
        BufferedWriter bw = null;
        boolean correcto = false;
        try {
            tarjeta = Environment.getExternalStorageDirectory();
            miFichero = new File(tarjeta.getAbsolutePath(), "frases.html");
            bw = new BufferedWriter(new FileWriter(miFichero));
            bw.write(cadena);
            Log.i("Información: ", miFichero.getAbsolutePath());
        } catch (IOException e) {
            if (cadena != null)
                Log.e("Error: ", cadena);
            Log.e("Error de E/S", e.getMessage());
        } finally {
            try {
                if (bw != null) {
                    bw.close();
                    correcto = true;
                }
            } catch (IOException e) {
                Log.e("Error al cerrar", e.getMessage());
            }
        }
        return correcto;
    }
}

Código del Servicio de Descarga

Deja una respuesta