En este momento estás viendo Cómo Crear App De Agenda En Android Studio

Cómo Crear App De Agenda En Android Studio

En está ocasión vamos a crear una App de Contactos para Android.

En primer lugar, nos dirigimos al archivo strings.xml, añadimos un texto que será el nombre de nuestra app.

<resources>
    <string name="app_name">Agenda</string>
</resources>

Ahora nos vamos al archivo colors.xml y añadimos los colores

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="colorTeban">#FF420042</color>
</resources>

Una vez editado, pasamos al archivo themes en su modo night y hacemos referencia a los colores que agregamos.

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.Curso5AAgenda" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>

        <item name="colorOnSecondary">@color/colorTeban</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorOnSecondary</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

Procedemos de la misma manera para la versión night.

Posteriormente nos dirigimos al archivo AndroidManifest.xml y agregamos los permisos para leer contactos y realizar llamadas.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mipaquete.agenda">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Curso5AAgenda">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Ahora nos dirigimos al archivo activity_main.xml, como se puede observar esta limpio y listo para que coloquemos nuestro código.

Colocamos el atributo gravedad y fondo.

Creamos un nuevo AppBarlayout, con ancho, altura y limites.

Dentro del appbarlayout creamos un toolbar con su identificador, ancho, alto y fondo.

Luego cerramos la etiqueta de appbarlayout, hacemos referencia al contenido principal donde estarán los contactos, que trabajaremos mas adelante.

Posteriormente colocamos un botón flotante, de igual manera con su identificador, ancho, alto, gravedad, márgenes, limites e icono.

Ahora nos dirigimos al archivo contact_detail.xml donde mostraremos lo detalles del contacto.

Dentro del linearlayout creamos un textview con su identificador, ancho, alto, texto y tamaño de texto.

Nos dirigimos al archivo que tiene el contenido principal, le añadimos el atributo para el comportamiento.

Creamos un ListView con su identificador, ancho, alto, márgenes, barras de desplazamiento y limites.

Ahora nos dirigimos al archivo item_user.xml, que será un elemento para la lista de contactos.

Colocamos un textview dentro del linear layout con su respectivo identificador, ancho, alto, márgenes, texto y tamaño de texto.

Ahora nos dirigimos al archivo listAdapter.java, creamos un constructor de la clase.

Sobrescribimos el método getview, para poder personalizar la lista de acuerdo a nuestras preferencias y poder enlazar con el archivo que creamos previamente, que era item_user.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:id="@+id/coordinator"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/ab_gradient"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorOnSecondary" />

    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/content_main" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:layout_marginStart="395dp"
        android:layout_marginEnd="411dp"
        android:layout_marginBottom="731dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</androidx.constraintlayout.widget.ConstraintLayout>

Luego nos dirigimos al archivo contact_detail.xml.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="24sp"
        tools:text="TextView" />
</LinearLayout>

Posteriormente nos dirigimos al archivo ListAdapter.java

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import java.util.ArrayList;

public class ListAdapter extends ArrayAdapter<User> {
    public ListAdapter(Context context, ArrayList<User> users) {
        super(context, 0, users);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        User user = getItem(position);
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_user, parent, false);
        }
        TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
        tvName.setText(user.name);
        return convertView;
    }
}

Luego nos dirigimos al archivo mainactivity.java y colocamos los atributos de listview, código de contactos y el botón flotante.

Dentro del método onCreate, instanciamos Toolbar y definimos como nuestra barra oficial, hacemos referencia al botón flotante y a la ListView.

Ahora colocamos una condición para saber si nuestra app tiene permiso para leer contactos, si los tiene entonces solicitara permiso para realizar llamadas.

En caso contrario mostrara un mensaje de que se necesitan permisos, luego colocamos un listener al ListView, donde configuramos el método onItemclick

Cuando se haga click en un item del listview, entonces se mostrar la pantalla para llamar al contacto, en caso contrario mostrara el mensaje para solicitar permisos.

Ahora volvemos a verificar el permiso para leer contactos, añadimos un listener al botón flotante, para mostrar la lista de contactos.

Colocamos un arraylist para almacenar los contactos.

Luego inicializamos uri para indicar la ruta desde donde los obtendremos, colocamos sort para ordenar ascendentemente

Inicializamos el cursor y colocamos sus parámetros por defecto.

Colocamos una condicional para saber si tiene items, en ese caso entonces recorrer el cursor.

Luego dentro del bucle vamos obteniendo los datos de los contactos.

Inicializamos otro cursor para obtener los números de los contacto y cerramos el cursor.

Luego inicializamos el adaptador y colocamos los contactos adentro.

Ahora colocamos al ArrayList contactNames el adaptador.

Por ultimo, colocamos el caso contrario por si no hay permisos para leer contactos, si no hay permisos, entonces mostrar un snackBar para otorgar permisos.

import java.util.ArrayList;
import java.util.List;

import static android.Manifest.permission.READ_CONTACTS;

import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;

public class MainActivity extends AppCompatActivity {
    private ListView contactNames;
    private static final int REQUEST_CODE_READ_CONTACTS = 1;
    FloatingActionButton fab = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        fab = findViewById(R.id.fab);
        contactNames = (ListView) findViewById(R.id.contact_names);

        if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_CONTACTS) + ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(
                    this,
                    new String[]{
                            Manifest.permission.CALL_PHONE,
                            Manifest.permission.READ_CONTACTS,
                    },
                    0
            );
        } else {
            try {
                Toast.makeText(getBaseContext(), "Se requieren permisos para llamar", Toast.LENGTH_SHORT).show();
            } catch(SecurityException e) {
                e.printStackTrace();
            }
        }

        contactNames.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                User user = (User)contactNames.getItemAtPosition(position);

                if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED) {
                    Intent callIntent = new Intent(Intent.ACTION_CALL);
                    callIntent.setData(Uri.parse("tel:"+user.telefono));
                    startActivity(callIntent);
                } else {
                    try {
                        Toast.makeText(getBaseContext(), "Se requieren permisos para llamar", Toast.LENGTH_SHORT).show();
                    } catch(SecurityException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        int hasReadContactPermission = ContextCompat.checkSelfPermission(this, READ_CONTACTS);
        if(hasReadContactPermission != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] {READ_CONTACTS}, REQUEST_CODE_READ_CONTACTS);
        }
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(ContextCompat.checkSelfPermission(MainActivity.this, READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
                    String[] projection = new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME};
                    ArrayList<User> contacts = new ArrayList<User>();

                    Uri uri = ContactsContract.Contacts.CONTENT_URI;
                    String sort = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME+" ASC";

                    Cursor cursor = getContentResolver().query(uri,
                            null,
                            null,
                            null,
                            sort);
                    if (cursor.getCount() > 0) {

                        while (cursor.moveToNext()) {

                            String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));

                            String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));

                            Uri uriPhone = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;

                            String selection = ContactsContract.CommonDataKinds.Phone.CONTACT_ID+" =?";

                            Cursor phoneCursor = getContentResolver().query(uriPhone, null, selection, new String[]{id}, null);
                            if(phoneCursor.moveToNext())
                            {
                                String number = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                                contacts.add(new User(name, number));

                            }
                            phoneCursor.close();
                        }
                        cursor.close();

                        ListAdapter adapter = new ListAdapter(getApplicationContext(), contacts);
                        contactNames.setAdapter(adapter);
                    }
                } else {
                    Snackbar.make(view, "Esta aplicación no puede mostrar tus contactos sin tu permiso", Snackbar.LENGTH_INDEFINITE)
                            .setAction("Autorizar permiso", new View.OnClickListener() {
                                        @Override
                                        public void onClick(View v) {
                                            if(ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, READ_CONTACTS)) {
                                                ActivityCompat.requestPermissions(MainActivity.this, new String[]{READ_CONTACTS}, REQUEST_CODE_READ_CONTACTS);
                                            } else {
                                                Uri uri = Uri.fromParts("package", MainActivity.this.getPackageName(), null);
                                                Intent intent = new Intent();
                                                intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(uri);
                                                MainActivity.this.startActivity(intent);
                                            }
                                        }
                                    }
                            ).show();
                }
            }
        });
    }
}

A continuación, te dejo un video con la implementación de App de Agenda.

Deja una respuesta