Contacts app in android device is a system app that comes installed on your android device. Different devices have different UI for the contacts app. In this article, we will take a look at how we can build our own contacts app in Android Studio.
What we are going to build in this article?
We will be building a simple application in which we will be displaying the list of contacts that are stored in the user’s device. Along with that we will be also adding a feature to save a new contact, filter contacts from the list using the search bar, and many more. Below is the video in which we will get to see what we are going to build in this article.
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.
Step 2: Add dependency and JitPack Repository
As we will have to request the user’s permissions to display contacts from the device in the app, that we have to ask for the user’s permissions. So for getting user’s permissions we will be using Dexter for getting user’s permissions in runtime. For using Dexter and we will be also using text drawable dependency for displaying text inside drawable now we have added the below dependency in build.gradle file. Navigate to the Gradle Scripts > build.gradle(Module:app) and add the below dependency in the dependencies section.
implementation ‘com.github.mukeshsolanki:photofilter:1.0.2’
implementation ‘com.karumi:dexter:6.2.2’
Add the JitPack repository to your build file. Add it to your root build.gradle at the end of repositories inside the allprojects{ } section.
allprojects {
repositories {
…
maven { url “https://jitpack.io” }
}
}
Now sync your project and we will move further for working with the AndroidManifest.xml file.
Step 3: Adding permissions in the AndroidManifest.xml
Navigate to the app > AndroidManifest.xml file and add the below permissions to it. Comments are added in the code to get to know in more detail.
<!--permissions to read contacts--> < uses-permission android:name = "android.permission.READ_CONTACTS" />
<!--permissions to write contacts--> < uses-permission android:name = "android.permission.WRITE_CONTACTS" />
<!--permissions to make a call--> < uses-permission android:name = "android.permission.CALL_PHONE" />
<!--permissions to send sms--> < uses-permission android:name = "android.permission.SEND_SMS" />
<!--permissions to write sms--> < uses-permission android:name = "android.permission.WRITE_SMS" />
|
After adding permissions now we will be moving towards creating a new activity for different screens in our app.
Step 4: Creating new empty activities
Creating a new activity for saving new contact:
Refer to the How to Create New Activity in Android Studio and name your activity as CreateNewContactActivity. This activity will be used for creating a new contact for our app.
Creating a new activity for displaying contact details:
Similarly, create another empty activity and name your activity as ContactDetailActivity. This activity will be used to make a call to that contact or for sending an SMS.
Step 5: Working with the activity_main.xml file
Navigate to the app > res > layout > activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file.
<? xml version = "1.0" encoding = "utf-8" ?>
< RelativeLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = ".MainActivity" >
<!--Recycler view for displaying list of contacts-->
< androidx.recyclerview.widget.RecyclerView
android:id = "@+id/idRVContacts"
android:layout_width = "match_parent"
android:layout_height = "match_parent" />
<!--progress bar for displaying loading-->
< ProgressBar
android:id = "@+id/idPBLoading"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_centerInParent = "true" />
<!--fab for adding a new contact-->
< com.google.android.material.floatingactionbutton.FloatingActionButton
android:id = "@+id/idFABadd"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentEnd = "true"
android:layout_alignParentBottom = "true"
android:layout_margin = "20dp"
android:src = "@drawable/ic_account"
app:fabCustomSize = "40dp"
app:tint = "@color/white" />
</ RelativeLayout >
|
Step 6: Creating a modal class for storing contacts
Navigate to the app > java > app’s package name > Right-click on it > New > Java class and name it as ContactsModal and add below code to it. Comments are added in the code to get to know in more detail.
public class ContactsModal {
// variables for our user name
// and contact number.
private String userName;
private String contactNumber;
// constructor
public ContactsModal(String userName, String contactNumber) {
this .userName = userName;
this .contactNumber = contactNumber;
}
// on below line we have
// created getter and setter
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this .userName = userName;
}
public String getContactNumber() {
return contactNumber;
}
public void setContactNumber(String contactNumber) {
this .contactNumber = contactNumber;
}
} |
Step 7: Creating a layout file for the item to be displayed in RecyclerView
Navigate to the app > res > layout > Right-click on it > New > Layout Resource file and name it as contacts_rv_item and add the below code to it. Comments are added in the code to get to know in more detail.
<? xml version = "1.0" encoding = "utf-8" ?>
< RelativeLayout
android:id = "@+id/idRLContact"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "3dp" >
<!--image view for displaying the first letter of contact-->
< ImageView
android:id = "@+id/idIVContact"
android:layout_width = "60dp"
android:layout_height = "60dp"
android:layout_margin = "8dp"
android:padding = "3dp"
android:src = "@mipmap/ic_launcher" />
<!--text view for displaying user name-->
< TextView
android:id = "@+id/idTVContactName"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_centerVertical = "true"
android:layout_marginStart = "8dp"
android:layout_marginTop = "12dp"
android:layout_marginEnd = "8dp"
android:layout_toRightOf = "@id/idIVContact"
android:text = "Contact Name"
android:textColor = "@color/black" />
</ RelativeLayout >
|
Step 8: Creating an adapter class for setting data to each item
Navigate to the app > java > your app’s package name > Right-click on it > New > Java class and name it as ContactsRVAdapter and add the below code to it. Comments are added in the code to get to know in more detail.
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.amulyakhare.textdrawable.TextDrawable;
import com.amulyakhare.textdrawable.util.ColorGenerator;
import java.util.ArrayList;
class ContactRVAdapter extends RecyclerView.Adapter<ContactRVAdapter.ViewHolder> {
// creating variables for context and array list.
private Context context;
private ArrayList<ContactsModal> contactsModalArrayList;
// creating a constructor
public ContactRVAdapter(Context context, ArrayList<ContactsModal> contactsModalArrayList) {
this .context = context;
this .contactsModalArrayList = contactsModalArrayList;
}
@NonNull
@Override
public ContactRVAdapter.ViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType) {
// passing our layout file for displaying our card item
return new ContactRVAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.contacts_rv_item, parent, false ));
}
// below method is use for filtering data in our array list
public void filterList(ArrayList<ContactsModal> filterlist) {
// on below line we are passing filtered
// array list in our original array list
contactsModalArrayList = filterlist;
notifyDataSetChanged();
}
@Override
public void onBindViewHolder( @NonNull ContactRVAdapter.ViewHolder holder, int position) {
// getting data from array list in our modal.
ContactsModal modal = contactsModalArrayList.get(position);
// on below line we are setting data to our text view.
holder.contactTV.setText(modal.getUserName());
ColorGenerator generator = ColorGenerator.MATERIAL; // or use DEFAULT
// generate random color
int color = generator.getRandomColor();
// below text drawable is a circular.
TextDrawable drawable2 = TextDrawable.builder().beginConfig()
.width( 100 ) // width in px
.height( 100 ) // height in px
.endConfig()
// as we are building a circular drawable
// we are calling a build round method.
// in that method we are passing our text and color.
.buildRound(modal.getUserName().substring( 0 , 1 ), color);
// setting image to our image view on below line.
holder.contactIV.setImageDrawable(drawable2);
// on below line we are adding on click listener to our item of recycler view.
holder.itemView.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are opening a new activity and passing data to it.
Intent i = new Intent(context, ContactDetailActivity. class );
i.putExtra( "name" , modal.getUserName());
i.putExtra( "contact" , modal.getContactNumber());
// on below line we are starting a new activity,
context.startActivity(i);
}
});
}
@Override
public int getItemCount() {
return contactsModalArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// on below line creating a variable
// for our image view and text view.
private ImageView contactIV;
private TextView contactTV;
public ViewHolder( @NonNull View itemView) {
super (itemView);
// initializing our image view and text view.
contactIV = itemView.findViewById(R.id.idIVContact);
contactTV = itemView.findViewById(R.id.idTVContactName);
}
}
} |
Step 9: Creating a new menu resource file for adding search view in the toolbar
Navigate to the app > res > Right-click on it > New > Android Resource directory and name it as menu after that right-click on the menu and click on New > Menu resource directory. After that name that files as search_menu and add the below code to it. Comments are added in the code to get to know in more detail. or you may refer to this article How to Create Menu Folder & Menu File in Android Studio?
<? xml version = "1.0" encoding = "utf-8" ?>
<!--creating an item for our search view-->
< item
android:id = "@+id/app_bar_search"
android:icon = "@drawable/ic_account"
android:title = "Search"
app:actionViewClass = "android.widget.SearchView"
app:showAsAction = "ifRoom|withText" />
</ menu >
|
Step 10: Working with the MainActivity.java file
Go to the MainActivity.java file and refer to the following code. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.
import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SearchView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.MenuItemCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// creating variables for our array list, recycler view progress bar and adapter.
private ArrayList<ContactsModal> contactsModalArrayList;
private RecyclerView contactRV;
private ContactRVAdapter contactRVAdapter;
private ProgressBar loadingPB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// on below line we are initializing our variables.
contactsModalArrayList = new ArrayList<>();
contactRV = findViewById(R.id.idRVContacts);
FloatingActionButton addNewContactFAB = findViewById(R.id.idFABadd);
loadingPB = findViewById(R.id.idPBLoading);
// calling method to prepare our recycler view.
prepareContactRV();
// calling a method to request permissions.
requestPermissions();
// adding on click listener for our fab.
addNewContactFAB.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// opening a new activity on below line.
Intent i = new Intent(MainActivity. this , CreateNewContactActivity. class );
startActivity(i);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// in this on create options menu we are calling
// a menu inflater and inflating our menu file.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
// on below line we are getting our menu item as search view item
MenuItem searchViewItem = menu.findItem(R.id.app_bar_search);
// on below line we are creating a variable for our search view.
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchViewItem);
// on below line we are setting on query text listener for our search view.
searchView.setOnQueryTextListener( new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
// on query submit we are clearing the focus for our search view.
searchView.clearFocus();
return false ;
}
@Override
public boolean onQueryTextChange(String newText) {
// on changing the text in our search view we are calling
// a filter method to filter our array list.
filter(newText.toLowerCase());
return false ;
}
});
return super .onCreateOptionsMenu(menu);
}
private void filter(String text) {
// in this method we are filtering our array list.
// on below line we are creating a new filtered array list.
ArrayList<ContactsModal> filteredlist = new ArrayList<>();
// on below line we are running a loop for checking if the item is present in array list.
for (ContactsModal item : contactsModalArrayList) {
if (item.getUserName().toLowerCase().contains(text.toLowerCase())) {
// on below line we are adding item to our filtered array list.
filteredlist.add(item);
}
}
// on below line we are checking if the filtered list is empty or not.
if (filteredlist.isEmpty()) {
Toast.makeText( this , "No Contact Found" , Toast.LENGTH_SHORT).show();
} else {
// passing this filtered list to our adapter with filter list method.
contactRVAdapter.filterList(filteredlist);
}
}
private void prepareContactRV() {
// in this method we are preparing our recycler view with adapter.
contactRVAdapter = new ContactRVAdapter( this , contactsModalArrayList);
// on below line we are setting layout manager.
contactRV.setLayoutManager( new LinearLayoutManager( this ));
// on below line we are setting adapter to our recycler view.
contactRV.setAdapter(contactRVAdapter);
}
private void requestPermissions() {
// below line is use to request
// permission in the current activity.
Dexter.withActivity( this )
// below line is use to request the number of
// permissions which are required in our app.
.withPermissions(Manifest.permission.READ_CONTACTS,
// below is the list of permissions
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS, Manifest.permission.WRITE_CONTACTS)
// after adding permissions we are
// calling and with listener method.
.withListener( new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
// this method is called when all permissions are granted
if (multiplePermissionsReport.areAllPermissionsGranted()) {
// do you work now
getContacts();
Toast.makeText(MainActivity. this , "All the permissions are granted.." , Toast.LENGTH_SHORT).show();
}
// check for permanent denial of any permission
if (multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
// permission is denied permanently,
// we will show user a dialog message.
showSettingsDialog();
}
}
@Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> list, PermissionToken permissionToken) {
// this method is called when user grants some
// permission and denies some of them.
permissionToken.continuePermissionRequest();
}
}).withErrorListener( new PermissionRequestErrorListener() {
// this method is use to handle error
// in runtime permissions
@Override
public void onError(DexterError error) {
// we are displaying a toast message for error message.
Toast.makeText(getApplicationContext(), "Error occurred! " , Toast.LENGTH_SHORT).show();
}
})
// below line is use to run the permissions
// on same thread and to check the permissions
.onSameThread().check();
}
// below is the shoe setting dialog
// method which is use to display a
// dialogue message.
private void showSettingsDialog() {
// we are displaying an alert dialog for permissions
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity. this );
// below line is the title
// for our alert dialog.
builder.setTitle( "Need Permissions" );
// below line is our message for our dialog
builder.setMessage( "This app needs permission to use this feature. You can grant them in app settings." );
builder.setPositiveButton( "GOTO SETTINGS" , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called on click on positive
// button and on clicking shit button we
// are redirecting our user from our app to the
// settings page of our app.
dialog.cancel();
// below is the intent from which we
// are redirecting our user.
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts( "package" , getPackageName(), null );
intent.setData(uri);
startActivityForResult(intent, 101 );
}
});
builder.setNegativeButton( "Cancel" , new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// this method is called when
// user click on negative button.
dialog.cancel();
}
});
// below line is used
// to display our dialog
builder.show();
}
private void getContacts() {
// this method is use to read contact from users device.
// on below line we are creating a string variables for
// our contact id and display name.
String contactId = "" ;
String displayName = "" ;
// on below line we are calling our content resolver for getting contacts
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null , null , null , ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " ASC" );
// on blow line we are checking the count for our cursor.
if (cursor.getCount() > 0 ) {
// if the count is greater than 0 then we are running a loop to move our cursor to next.
while (cursor.moveToNext()) {
// on below line we are getting the phone number.
int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if (hasPhoneNumber > 0 ) {
// we are checking if the has phone number is > 0
// on below line we are getting our contact id and user name for that contact
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
// on below line we are calling a content resolver and making a query
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null ,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?" ,
new String[]{contactId},
null );
// on below line we are moving our cursor to next position.
if (phoneCursor.moveToNext()) {
// on below line we are getting the phone number for our users and then adding the name along with phone number in array list.
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsModalArrayList.add( new ContactsModal(displayName, phoneNumber));
}
// on below line we are closing our phone cursor.
phoneCursor.close();
}
}
}
// on below line we are closing our cursor.
cursor.close();
// on below line we are hiding our progress bar and notifying our adapter class.
loadingPB.setVisibility(View.GONE);
contactRVAdapter.notifyDataSetChanged();
}
} |
Step 11: Working with the CreateNewContactActivity
Below is the code for both activity_create_new_contact.xml and CreateNewContactActivity.java file. Comments are added inside the code to understand the code in more detail.
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "vertical"
tools:context = ".CreateNewContactActivity" >
<!--edit text for user name-->
< EditText
android:id = "@+id/idEdtName"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "8dp"
android:hint = "Enter Name"
android:inputType = "text" />
<!--edit text for user phone number-->
< EditText
android:id = "@+id/idEdtPhoneNumber"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "8dp"
android:hint = "Enter Number"
android:inputType = "phone" />
<!--edit text for user email-->
< EditText
android:id = "@+id/idEdtEmail"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "8dp"
android:hint = "Enter Email Address"
android:inputType = "text" />
<!--button for saving a new contact-->
< Button
android:id = "@+id/idBtnAddContact"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "10dp"
android:text = "Save Contact"
android:textAllCaps = "false" />
</ LinearLayout >
|
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class CreateNewContactActivity extends AppCompatActivity {
// creating a new variable for our edit text and button.
private EditText nameEdt, phoneEdt, emailEdt;
private Button addContactEdt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_create_new_contact);
// on below line we are initializing our variables.
nameEdt = findViewById(R.id.idEdtName);
phoneEdt = findViewById(R.id.idEdtPhoneNumber);
emailEdt = findViewById(R.id.idEdtEmail);
addContactEdt = findViewById(R.id.idBtnAddContact);
// on below line we are adding on click listener for our button.
addContactEdt.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// on below line we are getting text from our edit text.
String name = nameEdt.getText().toString();
String phone = phoneEdt.getText().toString();
String email = emailEdt.getText().toString();
// on below line we are making a text validation.
if (TextUtils.isEmpty(name) && TextUtils.isEmpty(email) && TextUtils.isEmpty(phone)) {
Toast.makeText(CreateNewContactActivity. this , "Please enter the data in all fields. " , Toast.LENGTH_SHORT).show();
} else {
// calling a method to add contact.
addContact(name, email, phone);
}
}
});
}
private void addContact(String name, String email, String phone) {
// in this method we are calling an intent and passing data to that
// intent for adding a new contact.
Intent contactIntent = new Intent(ContactsContract.Intents.Insert.ACTION);
contactIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE);
contactIntent
.putExtra(ContactsContract.Intents.Insert.NAME, name)
.putExtra(ContactsContract.Intents.Insert.PHONE, phone)
.putExtra(ContactsContract.Intents.Insert.EMAIL, email);
startActivityForResult(contactIntent, 1 );
}
@Override
protected void onActivityResult( int requestCode, int resultCode, @Nullable Intent data) {
super .onActivityResult(requestCode, resultCode, data);
// in on activity result method.
if (requestCode == 1 ) {
// we are checking if the request code is 1
if (resultCode == Activity.RESULT_OK) {
// if the result is ok we are displaying a toast message.
Toast.makeText( this , "Contact has been added." , Toast.LENGTH_SHORT).show();
Intent i = new Intent(CreateNewContactActivity. this , MainActivity. class );
startActivity(i);
}
// else we are displaying a message as contact addition has cancelled.
if (resultCode == Activity.RESULT_CANCELED) {
Toast.makeText( this , "Cancelled Added Contact" ,
Toast.LENGTH_SHORT).show();
}
}
}
} |
Step 12: Working with the ContactDetailActivity
Below is the code for both activity_contact_detail.xml and ContactDetailActivity.java file. Comments are added inside the code to understand the code in more detail.
<? xml version = "1.0" encoding = "utf-8" ?>
< RelativeLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".ContactDetailActivity" >
<!--image view for contact-->
< ImageView
android:id = "@+id/idIVContact"
android:layout_width = "match_parent"
android:layout_height = "300dp"
android:background = "@color/purple_200"
android:padding = "50dp"
android:src = "@drawable/ic_account"
app:tint = "@color/white" />
<!--text view for displaying user name-->
< TextView
android:id = "@+id/idTVName"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_below = "@id/idIVContact"
android:background = "@color/purple_200"
android:padding = "8dp"
android:text = "Name"
android:textColor = "@color/white"
android:textSize = "18sp" />
<!--cardview for displaying user contact-->
< androidx.cardview.widget.CardView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_below = "@id/idTVName"
android:layout_marginStart = "4dp"
android:layout_marginTop = "20dp"
android:layout_marginEnd = "4dp"
app:cardCornerRadius = "4dp"
app:cardElevation = "4dp" >
< RelativeLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content" >
<!--image view for making a call -->
< ImageView
android:id = "@+id/idIVCall"
android:layout_width = "40dp"
android:layout_height = "40dp"
android:layout_margin = "8dp"
android:padding = "4dp"
android:src = "@drawable/ic_account"
app:tint = "@color/purple_700" />
<!--text view for displaying user contact-->
< TextView
android:id = "@+id/idTVPhone"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_centerVertical = "true"
android:layout_marginStart = "3dp"
android:layout_marginTop = "8dp"
android:layout_toStartOf = "@id/idIVMessage"
android:layout_toEndOf = "@id/idIVCall"
android:layout_toRightOf = "@id/idIVCall"
android:text = "Phone" />
<!--image view for displaying message icon-->
< ImageView
android:id = "@+id/idIVMessage"
android:layout_width = "40dp"
android:layout_height = "40dp"
android:layout_alignParentEnd = "true"
android:layout_margin = "8dp"
android:padding = "4dp"
android:src = "@drawable/ic_account"
app:tint = "@color/purple_700" />
</ RelativeLayout >
</ androidx.cardview.widget.CardView >
</ RelativeLayout >
|
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
public class ContactDetailActivity extends AppCompatActivity {
// creating variables for our image view and text view and string. .
private String contactName, contactNumber;
private TextView contactTV, nameTV;
private ImageView contactIV, callIV, messageIV;
@Override
protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_contact_detail);
// on below line we are getting data which
// we passed in our adapter class with intent.
contactName = getIntent().getStringExtra( "name" );
contactNumber = getIntent().getStringExtra( "contact" );
// initializing our views.
nameTV = findViewById(R.id.idTVName);
contactIV = findViewById(R.id.idIVContact);
contactTV = findViewById(R.id.idTVPhone);
nameTV.setText(contactName);
contactTV.setText(contactNumber);
callIV = findViewById(R.id.idIVCall);
messageIV = findViewById(R.id.idIVMessage);
// on below line adding click listener for our calling image view.
callIV.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to make a call.
makeCall(contactNumber);
}
});
// on below line adding on click listener for our message image view.
messageIV.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
// calling a method to send message
sendMessage(contactNumber);
}
});
}
private void sendMessage(String contactNumber) {
// in this method we are calling an intent to send sms.
// on below line we are passing our contact number.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse( "sms:" + contactNumber));
intent.putExtra( "sms_body" , "Enter your messaage" );
startActivity(intent);
}
private void makeCall(String contactNumber) {
// this method is called for making a call.
// on below line we are calling an intent to make a call.
Intent callIntent = new Intent(Intent.ACTION_CALL);
// on below line we are setting data to it.
callIntent.setData(Uri.parse( "tel:" + contactNumber));
// on below line we are checking if the calling permissions are granted not.
if (ActivityCompat.checkSelfPermission(ContactDetailActivity. this ,
Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return ;
}
// at last we are starting activity.
startActivity(callIntent);
}
} |
Now run your app and see the output of the app.
Note: For all the drawable files you may refer to the GitHub link or you may add it of your own.
Output:
Check out the project on below Github link: https://github.com/ChaitanyaMunje/GFG-Back4App/tree/ContactsApp