# Telephony

{% hint style="danger" %}

### Thank you for checking out the Telephony plugin. Unfortunately, this plugin is no longer actively maintained.

{% endhint %}

{% hint style="success" %}
[Check out on GitHub](https://github.com/shounakmulay/Telephony) &#x20;
{% endhint %}

**This plugin currently only works on Android Platform**

A Flutter plugin to use telephony features such as

* Send SMS Messages
* Query SMS Messages
* Listen for incoming SMS
* Retrieve various network parameters

This plugin tries to replicate some of the functionality provided by Android's [Telephony](https://developer.android.com/reference/android/provider/Telephony) class.

Check the [Features section](/#features) to see the list of implemented and missing features.

{% hint style="danger" %}

#### Telephony deals with features that require high risk or sensitive permissions.

Make sure that your app complies with the requirements of Google Play.\
\--> [https://support.google.com/googleplay/android-developer/answer/9214102](https://support.google.com/googleplay/android-developer/answer/9214102?hl=en)\
\--> <https://support.google.com/googleplay/android-developer/answer/9888170>
{% endhint %}

### Usage

To use this plugin add `telephony` as a [dependency in your pubspec.yaml file](https://flutter.dev/docs/development/packages-and-plugins/using-packages).

### Get Started

#### Setup

Import the `telephony` package

```dart
import 'package:telephony/telephony.dart';
```

Retrieve the singleton instance of `telephony` by calling

```dart
final Telephony telephony = Telephony.instance;
```

### Features

* [x] [Send SMS](/sending-an-sms)
* [x] [Query SMS](/query-sms)
  * [x] [Inbox](/query-sms#getinboxsms)
  * [x] [Sent](/query-sms#getsentsms)
  * [x] [Draft](/query-sms#getdraftsms)
* [x] [Query Conversations](/query-conversations)
* [x] [Listen to incoming SMS](/listen-incoming-sms)
  * [x] When app is in foreground
  * [x] When app is in background
* [x] [Network data and metrics](/network-data-and-metrics)
  * [x] [Cellular data state](/network-data-and-metrics#cellulardatastate)
  * [x] [Call state](/network-data-and-metrics#callstate)
  * [x] [Data activity](/network-data-and-metrics#dataactivity)
  * [x] [Network operator](/network-data-and-metrics#networkoperator)
  * [x] [Network operator name](/network-data-and-metrics#networkoperatorname)
  * [x] [Data network type](/network-data-and-metrics#datanetworktype)
  * [x] [Phone type](/network-data-and-metrics#phonetype)
  * [x] [Sim operator](/network-data-and-metrics#simoperator)
  * [x] [Sim operator name](/network-data-and-metrics#simoperatorname)
  * [x] [Sim state](/network-data-and-metrics#simstate)
  * [x] [Network roaming](/network-data-and-metrics#isnetworkroaming)
  * [x] [Signal strength](/network-data-and-metrics#signalstrengths)
  * [x] [Service state](/network-data-and-metrics#servicestate)
* [x] Start Phone Call
* [ ] Schedule a SMS
* [ ] SMS Retriever API


# Permissions

{% hint style="danger" %}
**Telephony will only request those permission that are listed in the&#x20;*****`AndroidManifest.xml`*****.**
{% endhint %}

Following necessary permissions are also listed at the top of every page.&#x20;

| Use Case                                                            | Permission        |
| ------------------------------------------------------------------- | ----------------- |
| [Sending An SMS](/sending-an-sms)                                   | **`SEND_SMS`**    |
| [Query SMS](/query-sms), [Query Conversation](/query-conversations) | **`READ_SMS`**    |
| [Listen Incoming SMS](/listen-incoming-sms)                         | **`RECEIVE_SMS`** |

### List Necessary Permissions

List the permission necessary for your use cases in your app's `AndroidManifest.xml`

{% code title="AndroidManifest.xml" %}

```markup
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
```

{% endcode %}

{% hint style="warning" %}
**Although this plugin will check and ask for permissions at runtime, it is advisable to&#x20;*****manually ask for permissions*****&#x20;before calling any other functions.**
{% endhint %}

### Request Phone and SMS Permissions

```dart
Telephony telephony = Telephony.instance;

bool permissionsGranted = await telephony.requestPhoneAndSmsPermissions;
```

### Request SMS Permissions

```dart
bool permissionsGranted = await telephony.requestSmsPermissions;
```

### Request Phone Permissions

```dart
bool permissionsGranted = await telephony.requestPhonePermissions;
```


# Sending An SMS

{% hint style="danger" %}
**Requires&#x20;*****`SEND_SMS`*****&#x20;permission.**
{% endhint %}

Add the following permission in your `AndroidManifest.xml`

```markup
<uses-permission android:name="android.permission.SEND_SMS"/>
```

## sendSms()

#### Returns Future\<void>

|   Parameters   | Type                                                             | Description                                                                                                                                                  | Optional | Default Value |
| :------------: | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------: | :-----------: |
|       to       | `String`                                                         | Number to send SMS to                                                                                                                                        |     ❌    |      `-`      |
|     message    | `String`                                                         | Message to send                                                                                                                                              |     ❌    |      `-`      |
|   isMultipart  | `bool`                                                           | If the body of the message is longer than the standard SMS length limit of `160 characters`, you can send a multipart SMS by setting the `isMultipart` flag. |    ✔️    |    `false`    |
| statusListener | [`SmsSendStatusListener`](/sending-an-sms#smssendstatuslistener) | Receives SMS sent and delivered events                                                                                                                       |    ✔️    |     `null`    |

```dart
Telephony telephony = Telephony.instance;

await telephony.sendSms(
    to: "1234567890",
    message: "May the force be with you!"
    );
```

If you want to listen to the status of the message being sent, provide[`SmsSendStatusListener`](/sending-an-sms#smssendstatuslistener) to the `sendSms` function.

```dart
final SmsSendStatusListener listener = (SendStatus status) {
    // Handle the status
    };

await telephony.sendSms(
    to: "1234567890",
    message: "May the force be with you!",
    statusListener: listener
    );
```

{% hint style="info" %}
**TIP:** \
If you want to send an sms to multiple numbers, you may pass multiple numbers separated by a `;`&#x20;

```dart
await telephony.sendSms(
    to: "1234567890;5724352435;24653456345",
    message: "May the force be with you!"
    );
```

Keep in mind that this method may not work on all devices.
{% endhint %}

## sendSmsByDefaultApp()

#### Returns Future\<void>

| Parameters | Type     | Description           | Optional |
| :--------: | -------- | --------------------- | :------: |
|     to     | `String` | Number to send SMS to |     ❌    |
|   message  | `String` | Message to send       |     ❌    |

Opens the default SMS app with the number and the message passed to the function.

```dart
await telephony.sendSmsByDefaultApp(
    to: "1234567890",
    message: "May the force be with you!"
    );
```

## SmsSendStatusListener

Receives `SendStatus` when SMS is `sent` and `delivered`.

```dart
SmsSendStatusListener listener = (SendStatus status) {
    // Handle the status
    };
```

## SendStatus

| Type | Values                  |
| ---- | ----------------------- |
| Enum | **`SENT`, `DELIVERED`** |


# Query SMS

{% hint style="danger" %}
**Requires&#x20;*****`READ_SMS`*****&#x20;permission.**
{% endhint %}

Add the following permission in your `AndroidManifest.xml`

```markup
<uses-permission android:name="android.permission.READ_SMS"/>
```

## getInboxSms()

#### Returns Future\<List<[SmsMessage](/query-sms#smsmessage)>>

| Parameters | Type                                        | Description                                                             | Optional | Default Value                                                                |
| :--------: | ------------------------------------------- | ----------------------------------------------------------------------- | :------: | ---------------------------------------------------------------------------- |
|   Columns  | List of [`SmsColumn`](/query-sms#smscolumn) | Columns to be returned by the query                                     |    ✔️    | \[ `SmsColumn.ID`, `SmsColumn.ADDRESS`, `SmsColumn.BODY`, `SmsColumn.DATE` ] |
|   Filter   | [`SmsFilter`](/query-sms#smsfilter)         | Filters the result by given constraints. Works like `SQL WHERE` clause. |    ✔️    | `null`                                                                       |
|  sortOrder | List of [`OrderBy`](/query-sms#orderby)     | Sorts the result prioritized by order of declaration.                   |    ✔️    | `null`                                                                       |

```dart
List<SmsMessage> messages = await telephony.getInboxSms(
        columns: [SmsColumn.ADDRESS, SmsColumn.BODY],
        filter: SmsFilter.where(SmsColumn.ADDRESS)
                 .equals("1234567890")
                 .and(SmsColumn.BODY)
                 .like("starwars"),
        sortOrder: [OrderBy(SmsColumn.ADDRESS, sort: Sort.ASC),
                OrderBy(SmsColumn.BODY)]
        );
```

#### All parameters are optional.

```dart
List<SmsMessage> messages = await telephony.getInboxSms();
```

## getSentSms()

#### Returns Future\<List<[SmsMessage](/query-sms#smsmessage)>>

| Parameters | Type                                        | Description                                                             | Optional | Default Value                                                                |
| :--------: | ------------------------------------------- | ----------------------------------------------------------------------- | :------: | ---------------------------------------------------------------------------- |
|   Columns  | List of [`SmsColumn`](/query-sms#smscolumn) | Columns to be returned by the query                                     |    ✔️    | \[ `SmsColumn.ID`, `SmsColumn.ADDRESS`, `SmsColumn.BODY`, `SmsColumn.DATE` ] |
|   Filter   | [`SmsFilter`](/query-sms#smsfilter)         | Filters the result by given constraints. Works like `SQL WHERE` clause. |    ✔️    | `null`                                                                       |
|  sortOrder | List of [`OrderBy`](/query-sms#orderby)     | Sorts the result prioritized by order of declaration.                   |    ✔️    | `null`                                                                       |

```dart
List<SmsMessage> messages = await telephony.getSentSms(
        columns: [SmsColumn.ADDRESS, SmsColumn.BODY],
        filter: SmsFilter.where(SmsColumn.ADDRESS)
                 .equals("1234567890")
                 .and(SmsColumn.BODY)
                 .like("starwars"),
        sortOrder: [OrderBy(SmsColumn.ADDRESS, sort: Sort.ASC),
                OrderBy(SmsColumn.BODY)]
        );
```

#### All parameters are optional.

```dart
List<SmsMessage> messages = await telephony.getSentSms();
```

## getDraftSms()

#### Returns Future\<List<[SmsMessage](/query-sms#smsmessage)>>

| Parameters | Type                                        | Description                                                             | Optional | Default Value                                                                |
| :--------: | ------------------------------------------- | ----------------------------------------------------------------------- | :------: | ---------------------------------------------------------------------------- |
|   Columns  | List of [`SmsColumn`](/query-sms#smscolumn) | Columns to be returned by the query                                     |    ✔️    | \[ `SmsColumn.ID`, `SmsColumn.ADDRESS`, `SmsColumn.BODY`, `SmsColumn.DATE` ] |
|   Filter   | [`SmsFilter`](/query-sms#smsfilter)         | Filters the result by given constraints. Works like `SQL WHERE` clause. |    ✔️    | `null`                                                                       |
|  sortOrder | List of [`OrderBy`](/query-sms#orderby)     | Sorts the result prioritized by order of declaration.                   |    ✔️    | `null`                                                                       |

```dart
List<SmsMessage> messages = await telephony.getDraftSms(
        columns: [SmsColumn.ADDRESS, SmsColumn.BODY],
        filter: SmsFilter.where(SmsColumn.ADDRESS)
                 .equals("1234567890")
                 .and(SmsColumn.BODY)
                 .like("starwars"),
        sortOrder: [OrderBy(SmsColumn.ADDRESS, sort: Sort.ASC),
                OrderBy(SmsColumn.BODY)]
        );
```

#### All parameters are optional.

```dart
List<SmsMessage> messages = await telephony.getDraftSms();
```

## SmsMessage

| Property             | Type                  |
| -------------------- | --------------------- |
| **`id`**             | `int`                 |
| **`address`**        | `String`              |
| **`body`**           | `String`              |
| **`date`**           | `int` in milliseconds |
| **`dateSent`**       | `int` in milliseconds |
| **`read`**           | `bool`                |
| **`seen`**           | `bool`                |
| **`subject`**        | `String`              |
| **`subscriptionId`** | `int`                 |
| **`threadId`**       | `int`                 |
| **`type`**           | `SmsType`             |
| **`status`**         | `SmsStatus`           |

## SmsColumn

| Columns               |
| --------------------- |
| **`ID`**              |
| **`ADDRESS`**         |
| **`BODY`**            |
| **`DATE`**            |
| **`DATE_SENT`**       |
| **`READ`**            |
| **`SEEN`**            |
| **`STATUS`**          |
| **`SUBJECT`**         |
| **`SUBSCRIPTION_ID`** |
| **`THREAD_ID`**       |
| **`TYPE`**            |

## SmsFilter

Generates a filter that will be used by an query. The methods read like an SQL query. The select part is determined `columns` parameter on one of the query methods. The `SmsFilter` handle the `WHERE` part.

#### Example

```sql
WHERE address = '123456789' 
AND body LIKE 'falcon'
OR date > '232123432'
```

#### Becomes

```dart
SmsFilter.where(SmsColumn.ADDRESS)
         .equals('123456789')
         .and(SmsColumn.BODY)
         .like('falcon')
         .or(SmsColumn.DATE)
         .greaterThan('232123432');
```

### Initializing a filter

Sms Filter works like a **`SQL WHERE`** clause. Initialize the filter by calling the **`where`** method and pass in the column name.

```dart
SmsFilter.where(SmsColumn.ID);
```

### Methods

#### equals()

Compares equality between the column values and the value provided to the function.

```dart
SmsFilter.where(SmsColumn.ID).equals('12');
```

#### greaterThan()

Adds a greater than `>` operator.

```dart
SmsFilter.where(SmsColumn.ID).greaterThan('2');
```

#### lessThan()

Adds a less than operator.

```dart
SmsFilter.where(SmsColumn.ID).lessThan('40');
```

#### greaterThanOrEqualTo()

Adds a greater than or equal to operator.

```dart
SmsFilter.where(SmsColumn.ID).greaterThanOrEqualTo('6');
```

#### lessThanOrEqualTo()

Adds a less than or equal to operator.

```dart
SmsFilter.where(SmsColumn.ID).lessThanOrEqualTo('30');
```

#### notEqualTo()

Checks for inequality.

```dart
SmsFilter.where(SmsColumn.ID).notEqualTo('14');
```

#### like()

Adds the **`LIKE`** operator.

```dart
SmsFilter.where(SmsColumn.BODY).like('%abc%');
```

#### inValues()

Adds the **`IN`** operator.

```dart
SmsFilter.where(SmsColumn.ID).inValues(['13', '15', '20']);
```

#### between()

Adds the **`BETWEEN`** operator.

```dart
SmsFilter.where(SmsColumn.ID).between('10','20');
```

#### not

Adds a **`NOT`** operator.

```dart
SmsFilter.where(SmsColumn.BODY).not.like('%a%');
```

### Combining Methods

#### and()

Adds the **`AND`** operator between two statements.

```dart
SmsFilter.where(SmsColumn.ID)
         .greaterThanOrEqualTo('6')
         .and(SmsColumn.BODY)
         .like('%abc%');
```

#### or()

Adds the **`OR`** operator between two statements.

```dart
SmsFilter.where(SmsColumn.ID)
         .greaterThan('10')
         .or(SmsColumn.ID)
         .lessThan('50');
```

## OrderBy

Creates an **`ORDER BY`** statement.

```dart
OrderBy(SmsColumn.ID);
```

Optionally you can provide a sort order. Defaults to **`DESC`**

```dart
OrderBy(SmsColumn.ID, sort: Sort.ASC);
```

## Sort

| Values     |
| ---------- |
| **`ASC`**  |
| **`DESC`** |


# Query Conversations

{% hint style="danger" %}
**Requires&#x20;*****`READ_SMS`*****&#x20;permission.**
{% endhint %}

Add the following permission in your `AndroidManifest.xml`

```markup
<uses-permission android:name="android.permission.READ_SMS"/>
```

## getConversations()

#### Returns Future\<List<[SmsConversation](/query-conversations#smsconversation)>>

| Parameters | Type                                                            | Description                                                             | Optional | Default Value |
| :--------: | --------------------------------------------------------------- | ----------------------------------------------------------------------- | :------: | ------------- |
|   Filter   | [`ConversationFilter`](/query-conversations#conversationfilter) | Filters the result by given constraints. Works like `SQL WHERE` clause. |    ✔️    | `null`        |
|  sortOrder | List of [`OrderBy`](/query-sms#orderby)                         | Sorts the result prioritized by order of declaration.                   |    ✔️    | `null`        |

```dart
List<SmsConversation> conversations = await telephony.getConversations(
        filter: SmsFilter.where(ConversationColumn.THREAD_ID)
                 .equals("12")
                 .and(ConversationColumn.SNIPPET)
                 .like("starwars"),
        sortOrder: [OrderBy(ConversationColumn.THREAD_ID, sort: Sort.ASC)]
        );
```

#### All parameters are optional.

```dart
List<SmsConversation> conversations = await telephony.getConversations();
```

## SmsConversation

| Property           | Type     |
| ------------------ | -------- |
| **`snippet`**      | `String` |
| **`threadId`**     | `int`    |
| **`messageCount`** | `int`    |

## ConversationColumn

| Values          |
| --------------- |
| **`SNIPPET`**   |
| **`THREAD_ID`** |
| **`MSG_COUNT`** |

## ConversationFilter

Works exactly like [`SmsFilter`](/query-sms#smsfilter) but works with [`ConversationColumn`](/query-conversations#conversationcolumn) instead of [`SmsColumn`](/query-sms#smscolumn)


# Listen Incoming SMS

## Setup

{% hint style="danger" %}
**Requires&#x20;*****`RECEIVE_SMS`*****&#x20;permission.**
{% endhint %}

To listen to incoming SMS add the `RECEIVE_SMS` permission to your `AndroidManifest.xml` file and register the `BroadcastReceiver`.

{% code title="AndroidManifest.xml" %}

```markup
<manifest>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>

    <application>
        ...
        ...

        <receiver android:name="com.shounakmulay.telephony.sms.IncomingSmsReceiver"
            android:permission="android.permission.BROADCAST_SMS" android:exported="true">
            <intent-filter>
            <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>

    </application>
</manifest>
```

{% endcode %}

## Usage

&#x20;**1.** Create a **top-level static function** to handle incoming messages when app is not is foreground.

{% hint style="warning" %}
**Avoid heavy computations in the background handler as Android system may kill long running operations in the background.**
{% endhint %}

```dart
backgrounMessageHandler(SmsMessage message) async {
    //Handle background message    
}

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

**2.** Call `listenIncomingSms` with a foreground `MessageHandler` and pass in the static `backgrounMessageHandler`.

{% hint style="info" %}
**Multipart message will be grouped together and delivered as a single SMS to the listenIncomingSms() function.**
{% endhint %}

```dart
telephony.listenIncomingSms(
     onNewMessage: (SmsMessage message) {
         // Handle message
     },
     onBackgroundMessage: backgroundMessageHandler
 );
```

#### Preferably should be called early in app lifecycle.

**3.** As of the `1.12` release of Flutter, plugins are automatically registered. This will allow you to use plugins as you normally do even in the background execution context.

```dart
backgrounMessageHandler(SmsMessage message) async {
     // Handle background message

     // Use plugins
     Vibration.vibrate(duration: 500);
 }
```

**4.** If you do not wish to receive incoming SMS when the app is in background, just do not pass the `onBackgroundMessage` parameter.

Alternatively if you prefer to expecility disable background execution, set the `listenInBackground` flag to `false`.

```dart
telephony.listenIncomingSms(
     onNewMessage: (SmsMessage message) {
         // Handle message
     },
     listenInBackground: false
 );
```


# Network Data and Metrics

{% hint style="info" %}
**Methods mentioned in this section call upon the relevant methods on Android's** [**`TelephonyManager`**](https://developer.android.com/reference/android/telephony/TelephonyManager) **class.**&#x20;

**Check** [**Android Develop Docs**](https://developer.android.com/reference/android/telephony/TelephonyManager) **for more details on how these methods function.**
{% endhint %}

## isSmsCapable

**Returns Future\<bool>**

Checks if the device has necessary features to send and receive SMS.

```dart
bool isSmsCapable = await telephony.isSmsCapable;
```

## cellularDataState

**Returns Future<**[**DataState**](/network-data-and-metrics#datastate)**>**

Returns a constant indicating the current data connection state (cellular).

```dart
DataState state = await telephony.cellularDataState;
```

## callState

**Returns Future<**[**CallState**](/network-data-and-metrics#callstate-1)**>**

Returns a constant that represents the current state of all phone calls.

```dart
CallState state = await telephony.callState;
```

## dataActivity

**Returns Future<**[**DataActivity**](/network-data-and-metrics#dataactivity-1)**>**

Returns a constant indicating the type of activity on a data connection (cellular)**.**

```dart
DataActivity activity = await telephony.dataActivity;
```

## networkOperator

**Returns Future\<String>**

Returns the numeric name (MCC+MNC) of current registered operator.&#x20;

Availability: Only when user is registered to a network.&#x20;

Result may be unreliable on CDMA networks (use [phoneType](/network-data-and-metrics#phonetype) to determine if on a CDMA network).

```dart
String networkOperator = await telephony.networkOperator;
```

## networkOperatorName

**Returns Future\<String>**

Returns the alphabetic name of current registered operator.&#x20;

Availability: Only when user is registered to a network.&#x20;

Result may be unreliable on CDMA networks (use [phoneType](/network-data-and-metrics#phonetype) to determine if on a CDMA network).

```dart
String operatorName = await telephony.networkOperatorName;
```

## dataNetworkType

**Returns Future<**[**NetworkType**](/network-data-and-metrics#networktype)**>**

{% hint style="danger" %}
**Requires `READ_PHONE_STATE` permission.**

Add the following in your `AndroidManifest.xml`

```markup
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
```

{% endhint %}

Returns a constant indicating the radio technology (network type) currently in use on the device for data transmission.

```dart
NetworkType type = await telephony.dataNetworkType;
```

## phoneType

**Returns Future<**[**PhoneType**](/network-data-and-metrics#phonetype-1)**>**

Returns a constant indicating the device phone type. This indicates the type of radio used to transmit voice calls.

```dart
PhoneType type = await telephony.phoneType;
```

## simOperator

**Returns Future\<String>**

Returns the MCC+MNC (mobile country code + mobile network code) of the provider of the SIM. 5 or 6 decimal digits.

Availability: [SimState ](/network-data-and-metrics#simstate)must be SIM\_STATE\_READY

```dart
String simOperator = await telephony.simOperator;
```

## simOperatorName

**Returns Future\<String>**

Returns the Service Provider Name (SPN).&#x20;

Availability: [SimState ](/network-data-and-metrics#simstate)must be SIM\_STATE\_READY

```dart
String simOperatorName = await telephony.simOperatorName;
```

## simState

**Returns Future<**[**SimState**](/network-data-and-metrics#simstate-1)**>**

Returns a constant indicating the state of the default SIM card.

```dart
SimState state = await telephony.simState;
```

## isNetworkRoaming

**Returns Future\<bool>**

Returns true if the device is considered roaming on the current network, for GSM purposes.&#x20;

Availability: Only when user registered to a network.

```dart
bool isNetworkRoaming = await telephony.isNetworkRoaming;
```

## signalStrengths

**Returns Future\<List<**[**SignalStrength**](/network-data-and-metrics#signalstrength)**>>**

{% hint style="danger" %}
**Requires Android build version 29 --> Android Q**
{% endhint %}

Returns a List of [SignalStrength](/network-data-and-metrics#signalstrength) or an empty List if there are no valid measurements.

```dart
List<SignalStrength> strenghts = await telephony.signalStrengths;
```

## serviceState

**Returns Future<**[**ServiceState**](/network-data-and-metrics#servicestate-1)**>**

{% hint style="danger" %}
**Requires Android build version 26 --> Android O**

**Requires permissions `ACCESS_COARSE_LOCATION` and `READ_PHONE_STATE`**

Add the following in your `AndroidManifest.xml`

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
```

{% endhint %}

Returns current voice service stat&#x65;**.**

```dart
ServiceState state = await telephony.serviceState;
```

## DataState

| Values             |
| ------------------ |
| **`DISCONNECTED`** |
| **`CONNECTING`**   |
| **`CONNECTED`**    |
| **`SUSPENDED`**    |
| **`UNKNOWN`**      |

## CallState

| Values        |
| ------------- |
| **`IDLE`**    |
| **`RINGING`** |
| **`OFFHOOK`** |

## DataActivity

| Values        |
| ------------- |
| **`NONE`**    |
| **`IN`**      |
| **`OUT`**     |
| **`INOUT`**   |
| **`DORMANT`** |

## NetworkType

| Values           |
| ---------------- |
| **`UNKNOWN`**    |
| **`GPRS`**       |
| **`EDGE`**       |
| **`UMTS`**       |
| **`CDMA`**       |
| **`EVDO_0`**     |
| **`EVDO_A`**     |
| **`TYPE_1xRTT`** |
| **`HSDPA`**      |
| **`HSUPA`**      |
| **`HSPA`**       |
| **`IDEN`**       |
| **`EVDO_B`**     |
| **`LTE`**        |
| **`EHRPD`**      |
| **`HSPAP`**      |
| **`GSM`**        |
| **`TD_SCDMA`**   |
| **`IWLAN`**      |
| **`LTE_CA`**     |
| **`NR`**         |

## PhoneType

| Values     |
| ---------- |
| **`NONE`** |
| **`GSM`**  |
| **`CDMS`** |
| **`SIP`**  |

## SimState

| Values                |
| --------------------- |
| **`UNKNOWN`**         |
| **`ABSENT`**          |
| **`PIN_REQUIRED`**    |
| **`PUK_REQUIRED`**    |
| **`NETWORK_LOCKED`**  |
| **`READY`**           |
| **`NOT_READY`**       |
| **`PERM_DISABLED`**   |
| **`CARD_IO_ERROR`**   |
| **`CARD_RESTRICTED`** |
| **`LOADED`**          |
| **`PRESENT`**         |

## **SignalStrength**

| Values                |
| --------------------- |
| **`NONE_OR_UNKNOWN`** |
| **`POOR`**            |
| **`MODERATE`**        |
| **`GOOD`**            |
| **`GREAT`**           |

## **ServiceState**

| Values               |
| -------------------- |
| **`IN_SERVICE`**     |
| **`OUT_OF_SERVICE`** |
| **`EMERGENCY_ONLY`** |
| **`POWER_OFF`**      |


# Start Phone Call

## openDialer()

| Parameters  | Type     | Description                                                        |
| ----------- | -------- | ------------------------------------------------------------------ |
| phoneNumber | `String` | The number that will be pre populated once the dialer is launched. |

Opens the default phone app or dialer with the supplied phone number.

```dart
await telephony.openDialer("123456789");
```

## dialPhoneNumber()

{% hint style="danger" %}

#### **Requires&#x20;*****`CALL_PHONE`*****&#x20;permission.**

{% endhint %}

Add the following to your `AndroidManifest.xml` file.

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

| Parameters  | Type     | Description                                         |
| ----------- | -------- | --------------------------------------------------- |
| phoneNumber | `String` | The phone number to which the call will be started. |

Starts a phone call to the provided phone number directly from your app.

```dart
await telephony.dialPhoneNumber("123456789");
```


# Executing in Background

If you want to call the `telephony` methods in background, you can do in the following ways.

**1. Using only Telephony.instance**

If you want to continue using `Telephony.insatnce` in the background, you will need to make sure that once the app comes back to the front, it again calls `Telephony.insatnce`.

```dart
backgrounMessageHandler(SmsMessage message) async {
    // Handle background message
    Telephony.insatnce.sendSms(to: "123456789", message: "Message from background")
}

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

class _MyAppState extends State<MyApp> {
  String _message;
  // This will not work as the instance will be replaced by
  // the one in background.
  final telephony = Telephony.instance;

   @override
  void initState() {
    super.initState();
    // You should make sure call to instance is made every time 
    // app comes to foreground
    final inbox = Telephony.insatnce.getInboxSms()
  }
```

**2. Use backgroundInstance**

If you cannot make sure that the call to instance would be made every time app comes to foreground, or if you would prefer to maintain a separate background instance, you can use `Telephony.backgroundInstance` in the background execution context.

```dart
backgrounMessageHandler(SmsMessage message) async {
    // Handle background message
    Telephony.backgroundInstance.sendSms(to: "123456789", message: "Message from background")
}

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

class _MyAppState extends State<MyApp> {
  String _message;
  final telephony = Telephony.instance;

   @override
  void initState() {
    super.initState();
    final inbox = telephony.getInboxSms()
  }
```


