Flutter Contacts List [Display Data And Make A Call]

flutter contacts list showing images of contact list and phone call screen

In this Flutter tutorial, we’ll learn how to get Flutter contacts list. We’ll fetch and display contact’s name, image and phone number. We’ll also redirect user to make a call, if the user taps on item(contact) of list. Everything will be discussed step by step using a practical code example in order for better understanding.

So what are we waiting for? Let’s jump right into its implementation phase.

Introduction: Flutter Contacts List

We’ll fetch contact’s data from phone and display it inside Flutter app. We’ll do the required settings for both android and IOS. We’ll import all the necessary packages as well.

Flutter contacts package is used to read, delete, update and delete contacts from device. In this tutorial, we’ll just learn how to read/fetch contact’s data.

We’ll also allow the user to tap on any specific item of list(contact) and it’ll navigate the user to make a call.

Implementing Flutter Contacts List (Step By Step)

Follow below steps in order to understand the complete process of fetching and displaying contacts data in Flutter app.

Step 1: Import Packages (Flutter Contacts, URL Launcher, Permission Handler)

  flutter_contacts: ^1.1.5+1
  url_launcher: ^6.1.7
  permission_handler: ^10.2.0

Flutter contacts – Its used to fetch Flutter contacts list in both android and IOS.

URL launcher – In our case, it will be used to redirect user to make a call.

Permission handler – Its used to allow/deny access to phone’s data.

These three packages are necessary to fetch contacts and redirect user to make a call. Import them in your pubspec.yaml file. See below image:

flutter pubspec yaml file flutter contacts package, url launcher package, permission handler package

Links to latest versions of these 3 packages are listed below.

  1. Flutter contacts – latest version
  2. URL launcher – latest version
  3. Permission handler – latest version

Step 2: Required Setup

For Android

Setup for android is given below.

1. AndroidX and Enable Jetifier

Set the androidX and enable jetifier to true, if not specified. The path is android/gradle.properties.

android.useAndroidX=true
android.enableJetifier=true

flutter androidx and enable jetifier

2. Compile SDK Version

Set the compile SDK version to more than 28. In our case, its 33. The path is android/app/build.gradle.

compileSdkVersion 33
flutter compile sdk version 33
3. Contact Permissions in Android Manifest XML

Add permissions to access device contacts information. The path is android/app/src/main/AndroidManifest.xml.

 <uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.WRITE_CONTACTS" />
flutter Contact Permissions in Android Manifest XML

For IOS

For IOS, we just need to add NSContactsUsageDescription in our Info.plist file. The path is ios/Runner/Info.plist.
 <key>NSContactsUsageDescription</key>
 <string>Reason we need access to the contact list</string>
flutter ios infoplist for flutter contacts list

Step 3: Coding

Now we’ve to do the coding part to fetch and display Flutter contacts list. Follow below steps for complete understanding.

1. Import Statements: Flutter Contacts and URL Launcher

First we’ve to specify the import statements. See below:
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:url_launcher/url_launcher_string.dart'; // use it if you want to redirect user to make a call 
Specify them in the dart file where you want to use them. In our case, we’ve specified it inside main.dart file as we’ll be doing the coding part in that file.

2. Function: Fetch and Store Flutter Contacts List

There are two methods through which we can fetch phone’s contact info. These are listed below:

Method 1: Partial Fetch
List<Contact> contactsList = await FlutterContacts.getContacts();
Method 2: Full Fetch
 List<Contact> contactsList = await FlutterContacts.getContacts(
      withProperties: true, withPhoto: true);

In our case, we’ll be using the second method which will fetch contact’s photo as well.

List<Contact>? contactsList;  // fetched contact's data will be stored in this list
  void getPhoneData() async {
    if (await FlutterContacts.requestPermission()) {
      contactsList = await FlutterContacts.getContacts(
          withProperties: true, withPhoto: true);
    }
    setState(() {});
  }
This function will first ask the user to allow/deny the permission to access contact’s data. If granted, then it’ll fetch data of Flutter contacts list with photos. If not, then no data will be fetched. Also the set state is used which will update the UI when this function is called.

We can trigger the function using a Flutter button as well. But in our case, we’ll be using the init state and inside it, we’ll call this function. Reason is that we want it to show the list of contacts whenever the screen loads. So when this screen loads, then it’ll ask the user for permission and if granted, then it’ll fetch the contact’s data.

3. Display Data (Name, Number, Picture)

In order to display the list of data, we’ve used Flutter listview builder.

We’ve displayed the fetched data inside Flutter container widgets that are returned by list view builder.

The complete source code will be provided in the end. In the meantime, we’ll just see the logical part.

We’ve specified a condition that if the list of contact’s data is empty then show Flutter circular progress indicator. If not, then display Flutter listview builder. See below:

contactsList == null ? show circular progress indicator : show list view builder

We’ve specified the length of list view builder to be the length of contact list items. See below:

itemCount: contactsList!.length
Display Images

We’ve used the below code to fetch available contact’s images. See below:

import 'dart:typed_data';   // for Uint8List
Uint8List? image = contactsList![index].photo;

It’ll store the available contact’s images. If the image is not available then it’ll show null.

As it’s used inside the list view builder so [index] is used to fetch items from list(contactsList) using indexing method.

In order to display the stored images, we’ve to use memory image. See below code:

MemoryImage(image!)

We’ve created a logic which will check if the image data is null then show the person icon. If not, then display image. Code for that will be available in the complete source code section.

Display Phone Numbers

We’ve created a logic that’ll store phone number in a string, if available. If not, then it’ll store double colons(–) as string. Its because sometimes we save the contact using email or some other info without specifying phone number. See below:

 String num = (contactsList![index].phones.isNotEmpty) 
                ? (contactsList![index].phones.first.number)  : "--";

It’s a simple if else condition which will check if the phone number is not empty then store the specified number, else store ().

In order to display it, we’ve used the Flutter text widget. See below:

Text(num)  // you can decorate the text using text style
Display Names

In order to display names, we’ve used the text widget. See below:

Text(contactsList![index].name.first) // its used to display first name
We can also get more info like:
contactsList![index].name.last             // get last name
contactsList![index].displayname           // get full name
contactsList![index].emails.first.address  // get email address - try it and share your experience with us co
contactsList![index].photo                 // get photo
Make A Call

We’ve used URL launcher which will navigate us to our device phone call section with the specified number(if available), whenever we click on any specified item of list. See below:

if (contactsList![index].phones.isNotEmpty) {
              launchUrlString('tel: ${num}');
                    }

So this is how we can easily fetch and display phone contact’s data. The complete source code is provided in the below section.

Fetch and Display Flutter Contacts List Source Code

phone contacts information displayed inside flutter listview builder

phone contact screen open using flutter app launch url string

import 'dart:typed_data';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:flutter/material.dart';
import 'package:flutter_contacts/flutter_contacts.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(debugShowCheckedModeBanner: false, home: HomePage());
  }
}
class HomePage extends StatefulWidget {
  const HomePage({super.key});
  @override
  State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {

  List<Contact>? contactsList;

  void getPhoneData() async {
    if (await FlutterContacts.requestPermission()) {
      contactsList = await FlutterContacts.getContacts(
          withProperties: true, withPhoto: true);
    }
    setState(() {});
  }

  @override
  void initState() {
    getPhoneData();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: contactsList == null
          ? Center(
              child: CircularProgressIndicator(),
            )
          : ListView.builder(
              itemCount: contactsList!.length,
              itemBuilder: (context, index) {

                Uint8List? image = contactsList![index].photo;
                String num = (contactsList![index].phones.isNotEmpty)
                    ? (contactsList![index].phones.first.number)
                    : "--";

                return GestureDetector(
                  onTap: () {
                    if (contactsList![index].phones.isNotEmpty) {
                      launchUrlString('tel: ${num}');
                    }
                  },
                  child: Container(
                    height: 70,
                    width: double.infinity,
                    margin: EdgeInsets.all(10),
                    padding: EdgeInsets.all(10),
                    decoration: BoxDecoration(
                        color: Colors.white,
                        borderRadius: BorderRadius.circular(10),
                        boxShadow: [
                          BoxShadow(
                              blurRadius: 5,
                              spreadRadius: 1,
                              offset: Offset(2, 2),
                              color: Colors.grey.shade300)
                        ]),
                    child: Row(
                      children: [
                        (contactsList![index].photo == null)
                            ? const CircleAvatar(child: Icon(Icons.person))
                            : CircleAvatar(
                                backgroundImage: MemoryImage(image!)),
                        SizedBox(
                          width: 20,
                        ),
                        Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Text(
                              contactsList![index].displayName,
                              style: TextStyle(
                                  fontSize: 18, fontWeight: FontWeight.w500),
                            ),
                            Text(num),
                          ],
                        )
                      ],
                    ),
                  ),
                );             
              }),
    );
  }
}

Conclusion

In conclusion, hope you now have a detailed practical knowledge of how to properly fetch and display Flutter contacts list. Don’t hesitate to share your amazing thoughts regarding this post.

We’d be very glad to see you visit our other tutorials on Flutter app development. Thank you for reading this article.

Leave a Comment

Your email address will not be published. Required fields are marked *