Android SDK

This page gives you all of the documentation needed to integrate the 2mee Android SDK. This page will be updated with any changes or new features added to the SDK.

Integration of the Appear2mee SDK into an Android App

This document will guide you through the example Appear2meeDemo app provided in the 2mee Android SDK showing how Face Messaging and rich text integration is achieved. This document refers to the sample Appear2meeDemo App. The sample code can be downloaded from https://www.2mee.com/SDK/Appear2meeSDKAndroid.zip Copy the link into a separate tab if it does not go to the page.

Introduction

Messages are sent from the 2mee Platform using push notifications. The notification includes the url/s of files that are required to display the notification. These files must be downloaded by the device in order to present the notification. When the firebase push notification is received an attempt is made to download any required files. If the message file cannot be downloaded a fallback text is “posted” as the notification. This fallback text is included in the notification and is set by your Platform user.

These messages are displayed initially as notification and in app as “dialogs”. Touching video/image notifications will give a larger view of the image/video. A video or sound can be paused/restarted by tapping on the middle of the image/video. Tapping on outside the middle will “accept” the message, and tapping on the X in at the top right corner will dismiss the large view, returning to the dialog.

Face messages appear within the app in developer selected positions dependant on the face type, see below for details. A touch on the face itself will “accept” the message a swipe anywhere else will dismiss the message as will a tap outside the face area. A double tap on the face will pause/restart the message.

Getting Started

Gradle

The Appear2mee SDK is accessed using the jitpack maven repository. To do this first add the repository in your root build.gradle at the end of repositories:

allprojects {
           repositories {
...
                maven { url 'https://jitpack.io' }
           }
}

Then add the Appear2meeSDKAndroid to the dependencies in the app build.gradle file.

dependencies {
  ...
  implementation 'org.bitbucket.2meeltd:Appear2meeSDKAndroid:1.2.1'
}

When building for android 12 / API 31 the app build.gradle file should also include compile options to allow target compatibility with Java version 11.

android {    
  ...
  compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11    
  } 
  ...  
 }

Older Gradle versions.

If you are using and older gradle and you cannot upgrade to version 7 you can use

dependencies {
  ...
  implementation 'org.bitbucket.2meeltd:Appear2meeSDKAndroid:1.2.0'
}

And

android {    
  ...
  compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8    
  } 
  ...  
 }

But all future updates will be for gradle 7+

Android Manifest

A 2mee enabled message app uses a number of components that are included in the SDK but must be given permission to use the AndroidManifest.xml file. These are the Appear2meeNotificationActivity that is called when a notification is selected. An internal JobService that downloads files. A broadcast receiver that is used to trigger the local notification at the correct time. Lastly the firebase messaging service that handles both incoming firebase notifications and deviceToken events to trigger sending the deviceToken to the 2mee Exchange.

Note: The Appear2meeNotificationActivity uses an openGL View. Apps by default allow openGL views, but if you app has hardwareAccelerated set to false, you will need to set it to true either for the whole app or just the Appear2meeNotificationActivity activity, in your AndroidManifest.xml.

<!-- Appear2mee Notification Activity -->
<activity
    android:name="com.twomee.appear2mee.Appear2meeNotificationActivity"
    android:parentActivityName=".MainActivity"
    android:hardwareAccelerated="true"
    android:launchMode="singleTop"
    android:theme="@style/Appear2mee.Translucent">
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.twomee.appear2meedemo.MainActivity" />
</activity>

<!-- Appear2mee Internal Job Service -->
<service
    android:name="com.twomee.appear2mee.Appear2meeJobService"
    android:exported="false"
    android:permission="android.permission.BIND_JOB_SERVICE"></service>

<!-- Appear2mee Internal Receiver triggered at Message Play Time -->
<receiver android:name="com.twomee.appear2mee.Appear2meeNotificationBroadcastReceiver" />

<!-- Appear2mee location service, used to trigger location data calls to 2mee exchange -->
<service android:name="com.twomee.appear2mee.Appear2meeLocationService"/>

<!-- Firebase Messaging  -->
<!-- Firebase Messaging default uses ad id. -->
<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@mipmap/ic_launcher" />
<service android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

There are also a number of permissions that need to be included in the manifest.

<uses-permission 
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />

See the demo app manifest file to copy paste to your app.

2mee Platform Setup

In order to link the App to the exchange it needs a Client ID and a secret key. These are generated in the 2mee Exchange. In order for the 2mee Exchange to connect to the App on the device firebase cloud messaging server key, and the senderID are required by the exchange. The exchange uses the server key to authorise sending push notifications and the sundered is used to check that deviceTokens registered on the exchange are for the same project as the server key. See the Getting Started for details of accessing the exchange keys and how to add the server key and senderid (also called the project id). The project server key are found in your firebase settings for your project.

Appear2mee Initialisation

The Appear2mee SDK needs to be setup in the Application class. This is where initialisation and callbacks are set. This is to ensure that SDK is setup when a notification is opened. Many Android apps do not override the standard Application class, so you may need to create one. It is important to indicate in the AndroidManifest.xml file the class name of the Application class used.

<application
    android:name=".Appear2meeApplication"
    android:allowBackup="true"
    android:fullBackupContent="@xml/my_backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity ……

Note, the use of the android:fullBackupContent=“@xml/my_backup_rules" this will be discussed later.

In any 2mee message app a connection to the 2mee Exchange is required. The exchange client id and secret key are generated on the 2mee exchange for each app administered on the exchange. If you are doing the exchange setup as well, see the 2mee Exchange Docs.

The init method Appear2mee.init is used allow the app to communicate with the exchange and respond to notifications. The function signature is public static <T extends Application & ResponseListenerCallback> void init(T app, String appear2meeID, String appear2meeKey). It requires the first argument to be of Application class which implements the Appear2mee.ResponseListenerCallback.

Note: All Appear2mee functions are class functions.

public class Appear2meeApplication extends Application 
                        implements Appear2mee.ResponseListenerCallback 
{
  static final String APPEAR2MEE_CLIENT_ID  = "<clientid>";
  static final String APPEAR2MEE_SECRET_KEY =<secretkey>";
 
  @Override
  public void onCreate() {
  super.onCreate();
  Appear2mee.init(this,APPEAR2MEE_CLIENT_ID, APPEAR2MEE_SECRET_KEY);
  // optional setupDefaults();
}

Notification View Icon

The default notification icons are 2mee png icons. To replace these icons you will need to name at least one image in your res/mipmap*** resources appear2mee_notification_icon, for the in notification icon. The status bar notification icon (which is normally white on transparent) is called appear2mee_notification_icon_small and should be included in your drawables. See an android icon maker to make this status bar icon.

Registering for and Remote Receive Notifications

The FirebaseMessagingService is used to both handle device tokens registration on the 2mee Exchange and also receiving then forwarding firebase messages. If you have not used the FirebaseMessagingService before you should read the documentation at https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService. Pay close attention to the manifest requirements. Note the older firebase api had a separate FirebaseInstanceIdService, that service is now incorporated into the FirebaseMessagingService.

If you are not familiar with firebase then you should read the requirements for android setup at https://firebase.google.com/docs/android/setup. If you are setting up a new project you will need to add the google-services.json to your project. This is found in your firebase project settings.

Registering the Device Token

The app requires FirebaseMessageServices class, see the example app. The onNewToken method should contain a Appear2mee call to registerDeviceToken. This method will register the app on the exchange.

@Override
public void onNewToken(String token) {
    Log.d(TAG, "DeviceToken: " + token);
    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // Instance ID token to your app server.
    Appear2mee.registerDeviceToken(token);
}

Receiving Remote Notifications

Push notifications are handled in the FirebaseMessagingService onMessageReceived, exchange messages are data messages, and are handled using the Appear2mee.onMessageReceived function.

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
  boolean isMessageAppear2mee = 
 Appear2mee.onMessageReceived(remoteMessage);
  if (isMessageAppear2mee) {
        // nothing to do. Already handled.
  } else {
        sendNotification(remoteMessage);
  }
}

The Appear2mee.onMessageReceived determines if the message is from the 2mee Exchange. If it is not a 2mee Exchange notification the function will return false and pass control back to allow the developer to handle the notification. If the function returns true the notification has been fully processed by the SDK.

On receiving the notification the Appear2mee SDK will download any files associated with the message (if it has download permission) and will schedule an internal alarm at the play time the message has defined. If the message has expired the message will be ignored. The alarm when triggered will send a local notification.

Important: If permission is not granted for write/read file access the app cannot download any files associated with the message from the exchange.

Responding to Local Notifications

Remote push notifications are sent by the 2mee Exchange to your app, these notifications do not include an alert so that on receipt they are silent. The Appear2mee SDK has to process these notifications, downloaded any files and schedule an internal alarm at the play time. When the alarm is triggered the Appear2mee SDK displays a local notification

When the user interacts with the local notification it can be dismissed or “accepted”. If the notification was accepted the app will to come into the foreground or launch, and the Appear2meeNotificationActivity is started. When Appear2meeNotificationActivity launches it calls the appear2meeResponseListener callback function in the Application class (which must implement Appear2mee.ResponseListenerCallback). The appear2meeResponseListener callback returns a Appear2mee.ResponseListener, which determines what actions are taken when the user dismisses/accepts the dialog or face message. For example,

@Override
public Appear2mee.ResponseListener appear2meeResponseListener(
     Bundle payload)
{
    return new Appear2mee.ResponseListener() {
        @Override
        public void acceptAction(Map<String, String> keyValueDict) {
            Toast.makeText(Appear2meeApplication.this, 
             String.format("key/values %s”,keyValueDict.toString()),
                                          Toast.LENGTH_LONG).show();
        }
        @Override
        public void dismissAction(Map<String, String> keyValueDict) {
            Toast.makeText(Appear2meeApplication.this,”Dismissed",
                                             Toast.LENGTH_LONG).show();
        }
    };
}

In the Appear2meeNotificationActivity images/Animations/Videos are shown with a simple popup dialog with dismiss and accept buttons. A face message is shown with a popover where a swipe action outside the face will be a dismiss and a touch on the face will be an accept. These “dialog” responses will call the appropriate dismiss or accept listener action function.

The dismissAction/acceptAction functions are called with a dictionary of key/values that were attached to the notification in the 2mee Exchange. Typically they can be used to perform some action based on the values present. For example, move to a page on the app {“page”:”sports/mens/shorts”}.

Note: Notifications can be cleared in the notification drawer, in which case the app does not get any response.

Auto backup

Apps that target Android 6.0 (API level 23) or higher are automatically enabled for Auto Backup. However some of the Appear2mee SDK app data should not be backed up. It includes the device token and device specific data connecting the device to the 2mee Exchange. If a new device uses a backup it can lead to two devices connected to the same device entry and potentially a clash of settings. The userID and tags are stored in a different sharepref, and will be backed up. These are the links between the app and the actual user.

In order to avoid this the demo app uses an option to define which preferences are backed up.

<application
    android:name=".Appear2meeApplication"
    android:allowBackup="true"
    android:fullBackupContent=“@xml/my_backup_rules"

In resources a file res/xml/my_backup_rules.xml defines which data to exclude from backup.

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <exclude domain="sharedpref" path="APPEAR2MEE.xml"/>
</full-backup-content>

Further Steps

After completing the App setup the app will be functional. There are other options that you might need to setup within the app.

Customisation with userID

Many apps are linked to a separate system and have some kind of user identity. The SDK allows the app to store a userID. The 2mee exchange can return reports based on a user supplied userID. This id should be a string and can be supplied after the init of the Appear2mee SDK using the class method Appear2mee.registerUserID. If a userID is not supplied the device token is used as the userID. In the demo app there is a button [userID] that can be used to open a text dialog to input a userID.

Tags

In order to customise face messages to an individual user, a tag system is used. This allows the developer to send tags to the exchange that are indicative of the content to be sent to a particular user. The 2mee Exchange uses the tags set to a corresponding deviceToken to determine which messages a device should be sent.

Tags can be set using internal logic, for example game level, previous activity etc. Alternatively tags can be sent to an individual device, by a custom scheme of the developers choosing, and should then be forward to the exchange via the tags system.

Tags are represented as a dictionary (Map<String,String>), and are stored using the Appear2mee class method, registerTags. The tags that have already been stored can be retrieved using the Appear2mee class method, tags; For example,

Map<String, String> map = new HashMap<String, String>();
map.put("favColor", "red");
map.put("job", "superman");
Appear2ee.registerTags(map);
Map<String, String> tags = Bridge2Mee.getTags();
tags.put("job", "batman");
Appear2mee.registerTags(tags);

Note that tags dictionary is saved as a whole. To add a new tag, the original tags dictionary must be extended, then registered.

In App Messages

The SDK also allows the "pulling" of named messages from the 2mee Exchange. Currently only holocapsule messages (these are face videos) can be displayed in app. In order to retrieve a message the Appear2mee getMessage: method is used. A callback is called when the message is ready to display or has failed. If the message item is not null it can then be displayed.

public void onMessageClick(View view) {
    Appear2mee.getMessage("Welcome Message", new Appear2mee.MessageReadyListener() {
        @Override
        public void ready(String name, Bundle item) {
            if(item == null) return;
            Appear2mee.displayMessage(item,name); // use name as userData
        }
    });
}

The displayMessage method uses the same callbacks method for "accept" and "dismiss" as notifications. It allows for adding some extra user data so that the ResponseListener can be tailored to the message. In your Application class the appear2meeResponseListener can read the userData which is added to the Bundle.

@Override
public Appear2mee.ResponseListener appear2meeResponseListener(
     Bundle payload)
{
    final String wasMessage = payload.getString("userData");
    if(wasMessage != null) {
        return new Appear2mee.ResponseListener() {
            @Override
            public void acceptAction(Map<String, String> keyValueDict) {
                Toast.makeText(Appear2meeApplication.this , String.format(Locale.US,"userData:%s key/values %s",wasMessage,keyValueDict.toString()), Toast.LENGTH_LONG).show();
            }
            @Override
            public void dismissAction(Map<String, String> keyValueDict) {
                Toast.makeText(Appear2meeApplication.this , String.format(Locale.US,"userData:%s Dismissed",wasMessage), Toast.LENGTH_LONG).show();
            }
        };
    }
    return new Appear2mee.ResponseListener() {
        @Override
        ............
    };

Location Service

The 2mee Exchange can send notifications based on the users last recorded location. In order to send the device location to the exchange some setup is required, if this is not done no location data is sent.

In order to start sending location information the SDK must have permission. In Android permissions can only be generated in an Activity so the call to start collection locations must be done in an Activity. Normally that would be done in your main activity and in the onCreate function using the Appear2mee.startLocationService method.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ....
    ....
    Appear2mee.startLocationService(this);
}

The method with request permissions if required and therefore the activity needs to implement the ActivityCompat.OnRequestPermissionsResultCallback.

public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback  {

In particular it is required to implement the onRequestPermissionsResults callback so that if permissions were requested (normally only the first time the app is used) the Appear2mee.startLocationServices can be called.

/**
 * ResponseListenerCallback received when a permissions request has been completed.
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                       @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode == Appear2mee.LOCATION_SERVICE_REQUEST_CODE) { // you do not need to check the requestCode
        Appear2mee.startLocationService(this);
    }
}

The location service is as the name suggests a service and a reference to the service must appear in the application AndroidManifest.xml file. See the manifest section.

<!-- Appear2mee location service, used to trigger location data calls to 2mee exchange -->
<service android:name="com.twomee.appear2mee.Appear2meeLocationService"/>

The default message for location rational can be change using the Appear2mee.kLocationRationalMessage setting. See the Custom Settings section for details.

Custom Settings

The Appear2mee SDK has a limited number of settings to change the appearance of notifications and the default text that appears in notifications. These customisations are set using a dictionary of values (Map<String,String>).

Default texts for the dialog buttons, cane assigned, but the kNotificationAccept, “OK” option will normally be will be overridden by the payload sent by the 2mee Exchange.

Map<String,String> defaultSettings = new HashMap<>();
   defaultSettings.put(Appear2mee.kNotificationDismiss,"Dismiss");
   defaultSettings.put(Appear2mee.kNotificationAccept,”OK");

When a notification has expire, that is the accept action is no longer available, extra text is added to the dialog. The default is “Sorry, opportunity missed!” but can be changed.

defaultSettings.put(Appear2mee.kMessageExpired,
 "Sorry, opportunity missed!”);

The position of face messages can be altered, standard faces, without shoulders or torso can be displayed in any corner or the centre of the screen. If displayed in the centre of the screen a background is used. The color of this background is another of the defaults. The default it is white, but, of course can be set to clear or any other color. The position of face messages with shoulders or torso is restricted to bottom left or right corners. This is because these formats have a bottom edge which looks better against the edge of the screen. If there are issues in your screen layout centre can also be used.

// Position of facee in app.
defaultSettings.put(Appear2mee.kFaceHeadPosition,
                             Appear2mee.kFaceHeadTopRight);
defaultSettings.put(Appear2mee.kFaceShouldersPosition,
                             Appear2mee.kFaceShouldersRight);

The color of the face background when displayed in the centre of the screen can also be changed.

// Color of face background, only used with Appear2mee.kFaceHeadCenter
// setting for Appear2mee.kFaceHeadPosition:
defaultSettings.put(Appear2mee.kFaceCenterBackgroundColor,  
                                Appear2mee.colorToString(Color.WHITE));

When the notification dialog is displayed the screen is faded by a background view with a color. The default uses some transparency so that the context can still be seen. The default can be changed as shown below. Colors are converted to a string using an Appear2mee helper function Appear2mee.colorToString.

//Color of app dialog background (for rich texts only)
defaultSettings.put(Appear2mee.kDisplayBackgroundColor, 
        Appear2mee.colorToString(Color.argb((int)(0.6*255),0,0,0)));

The color of the background when a face message is displayed can also be changed.

defaultSettings.put(Appear2mee.kFaceDisplayBackgroundColor,
        Appear2mee.colorToString(Color.argb((int)(0.6*255),0,0,0)));

Notifications sounds are built into the SDK. But can be changed if required, the face notification soun

defaultSettings.put(Appear2mee.kFaceNotificationSound, 
     String.format(Locale.US,%d”,R.raw.appear2meefacesound));
defaultSettings.put(Appear2mee.kNotificationSound, 
     String.format(Locale.US,%d”,R.raw.appear2meefacesound));

The default message for location rational can be change using the Appear2mee.kLocationRationalMessage setting.

defaultSettings.put(Appear2mee.kLocationRationalMessage,
 "Location Services are needed to send you notifications that are relevant to your current position.");

The 2mee Exchange has an option to open an external webpage when a notification dialog has been accepted. The default action is to not call the accept action listener method, and to start the external browser with the address given. Where this default action is not wanted the setting Appear2mee.kOpenExternalURLAutomatically should be set to “false”. It is then up to the developer to handle the key “__OpenExternalURL”.

  defaultSettings.put(Appear2mee.kOpenExternalURLAutomatically,"true");

The defaults are set using the Appear2mee.defaultSettings class method, which merges with any existing defaults. These defaults are not stored so should always be set on app startup.

    // This merges settings with existing settings.
    Appear2mee.defaultSettings(defaultSettings);

Message Permissions

The developer may choose to allow users of the app to not receive messages form the exchange. Other permissions control the download of files (rich messages) or to receive them only when they are connected via WiFi. When file downloads are not permitted the messages are still received but the text uses the fallback text message configured at the exchange. The default setting are to allow messages with no restriction on the method of download.

Note: Once set permissions are stored by the Appear2mee SDK so that when the app is restarted the same permissions are set.

Note: the SDK will not restrict itself to using only WiFi for other tasks, in particular communications to the exchange will use 3G/4G networks. However these communication are small packets of data, normally in the region of a few tens of bytes.

The Appear2mee class method servicePermission is used to set whether the 2mee exchange should send any messages to the device. Of course the device has to report this state to the exchange before it can take effect.

public static void  servicePermission(boolean  allowService)

The class method,

public static boolean hasServicePermission()

is used to determine services permission State.

The class method downloadPermission is used to set whether face message videos are download.

public static void downloadPermission(boolean allowDownload)

This method does not stop the alerts. The alerts can however be changed to use a fallback text, either from the exchange or hardcoded by the developer in the service extension.The class method,

public static boolean hasDownloadPermission()

is used to determine if permission is given for downloads. And can be used to determine if fallback text should be provided in a service extension.

The class method,

public static void  WifiOnlyPermission(boolean onlyWifi)

is used to set the Wifi permission. The default is false, that is Wifi is permitted. The method

public static boolean hasWifiOnlyPermission()

is used to determine the state of WifiOnly permission.

Test Notifications

The Appear2meeSimple app is a device app only. It does not run in a simulator. The main displays consists of number of buttons and switches. One of the switches allows notifications to be sent to the system notification center when the app is in the foreground. Allowing all notifications that are received to be processed in the same way will simplify how you integrate 2mee messaging into your own App.

Two of the buttons simulate receiving a push notification, they actually send local notifications. They do not test the service extension, as that needs a push notification to be triggered. If the “Always display as a local notification” switch is on, a local notification will appear, else a dialog will appear. See the code in the ViewController.m in the test app to change these notification. You can find some other examples of the push notification structure in the APNS folder of the demo project.

Remote Notification Testing

In order to send notifications you will need the cloud messaging server key, the legacy key works as well. This key can be found in your firebase project settings under the cloud messaging tab.

To test how your app responds to remote notifications a notification payload can be sent using for example pushtry. The firebase notification tool cannot be used as it does not allow the sending of json data. You will also need the deviceToken from the test device running the App. The Appear2meeDemo app logs the deviceToken when it is generated, search for deviceToken in the logs.

Note: Make sure your playtime/expire times are valid, unless of course you are testing what happens when a message has expired.

Note: Expiry is in seconds.

Note: A Push will over write an existing notification in the notification centre which has the same jobId.

Check List

Appear2mee SDK Check List

App

Download firebase project google-services.json

Get Exchange Keys, ClientID and Key, for Appear2mee init.

Appear2mee Services and Activities in AndroidManifest

Required permissions in AndroidMainifest

Add Appear2mee SDK AAR as module.

Generate custom Application class. Implements ResponseListenerCallback

Application Class Name in AndroidMainifest

Implement ResponseListener, accept/dismiss actions

Add auto backup options to AndroidManifest, and exclude file to Resources

Add appear2mee_notification_icon to resources (mipmap)

Add appear2mee_notification_icon_small to resources (drawables)

FirebaseMessagingService Class Extension

Register deviceToken in onNewToken function

Handle Appear2mee Notifications in onMessageReceived Function.

Handle other Notifications in onMessageReceived Function.

SDK Changes

V1.0.2

Bug fix, engaged was not reported to exchange for rich text notifications. Large message view for image/videos.

V1.0.3

Reporting to 2mee Exchange improved to match iOS. Notification files stored in internal memory.

Bug fix: __openExternalURL needed protecting from bad urls.

V1.0.4

Changes to allow xamarin bindings to compile more easily.

V1.0.15

Version numbering change to match iOS. Dark mode changes to allow light text in notifications. Defined appear2meeLight color.

V1.0.21

Fixes to send locale data to exchange. As Android locale does not appear to be consistent used the telephone country setting to define country.

Last updated