Useful commands

Welcome to the useful commands section

Here, we suggest you some methods in order to quickly and efficiently perform certain actions within the SDK. 

Restrict SDK connection

You can temporarily restrict the connections in order to tell our SDK to stop flushing network requests.

 A4S.get(this).setRestrictedConnection(true);

All requests will be locked until you use setRestrictedConnection(false). In order to know if the connection is restricted for our SDK, please use:

 A4S.get(this).isRestrictedConnection(new Callback<Boolean>() {

    @Override
    public void onResult(Boolean locked) {
        //Get the result here
    }
});

Set a tracking mode

If you need it, tracking can now be restricted in order to be compliant to the most severe privacy rules. This is not needed for most integrations

Add the following string:

strings.xml

<resources>
    // ...

    <string name="acc_tracking_mode">Normal</string>
</resource>

Set cache delay

If you want the SDK network requests to be executed more or less often, you can set a custom delay for our cache system.

Add the following string:

<resources>
    // ...

    <string name="acc_cache_delay">15</string>
</resource>

Where 15 represents the delay in seconds before each execution of cached requests.

Stopping the SDK

If a user wants to opt-out from tracking, you can use this static method:

 A4S.setDoNotTrackEnabled(this, true);

Where "this" is any Android context like: Application, Activity, BroadcastReceiver...

If you want to know whether the user is being tracked or not, use the following static function:

 A4S.isDoNotTrackEnabled(this);

Custom Credentials Integration

If you need to provide programmatically partner Id and private Key to the SDK, you can implement our com.ad4screen.sdk.AccIdsContentProvider interface in your class and provide your credentials. Both getPartnerId() and getPrivateKey() must return values as fast as possible, so never do any long running operations in the methods.

Usage

Implement the AccIdsContentProvider interface:

MyAccIdsContentProvider.java

package your.package.MyAccIdsContentProvider;

import com.ad4screen.sdk.AccIdsContentProvider;

public class MyAccIdsContentProvider extends AccIdsContentProvider {
    @Override
    protected String getPartnerId() {
        return "comptedemosdk29j175fb8ad2904";
    }
    @Override
    protected String getPrivateKey() {
        return "78dbaf3fac52784ad5f26a3fcf27996983ba92fd";
    }
}

Please note that if your provider returns null values, SDK will not start and will retry to get a partner id/private key by calling your provider every 10 sec

Add the provider tag to your AndroidManifest.xml file:

AndroidManifest.xml

// ...

    <provider
            android:name=".MyAccIdsContentProvider"
            android:authorities="${applicationId}.accengage.ids"
            android:exported="false"
            android:multiprocess="false" />

</application>

Update credentials

Two instances of your class implementing AccIdsContentProvider are created at the first access to the SDK by calling A4S.get() method. At the same time the SDK call getPartnerId() and getPrivateKey() to obtain credentials. These credentials will be used by the SDK until the application will not be restarted (killed and relaunched).

To apply new values at runtime, for example, if you need to change a country with another partner ID and private key without restarting the app, you need to use A4S.get(context).reinitPartnerId(). The method will call getPartnerId() and getPrivateKey() of your class to obtain new credentials, and then reinitialize the SDK.

FCM/GCM Sender IDs

On the table below you can find different combinations of FCM/GCM plugins and Sender IDs:

acc_sender_id acc_firebase_app_id plugin  description

-

- -  
- - firebase Default FirebaseApp instance uses a Sender ID from google-services.json. A token will be sent to Accengage servers. The firebase plugin will listen messages from the FCM Sender ID.
fcm:YOUR_SENDER_ID - firebase Default FirebaseApp instance uses a Sender ID from google-services.json and another Sender ID from strings.xml. A token of the Sender ID from strings.xml will be sent to Accengage servers. The firebase plugin will listen messages from 2 FCM Sender IDs.
fcm:YOUR_SENDER_ID YOUR_APP_ID firebase Default FirebaseApp instance uses a Sender ID from google-services.json and a new Accengage FirebaseApp instance uses another Sender ID from strings.xml. A token of the Sender ID from strings.xml will be sent to Accengage servers. The firebase plugin will listen messages from 2 FCM Sender IDs.
gcm:YOUR_SENDER_ID - firebase Default FirebaseApp instance uses a Sender ID from google-services.json and another Sender ID from strings.xml. A token of the Sender ID from strings.xml will be sent to Accengage servers. The firebase plugin will listen messages from 2 Sender IDs (FCM and GCM).
gcm:YOUR_SENDER_ID YOUR_APP_ID firebase Default FirebaseApp instance uses a Sender ID from google-services.json and a new Accengage FirebaseApp instance uses another Sender ID from strings.xml. A token of the Sender ID from strings.xml will be sent to Accengage servers. The firebase plugin will listen messages from 2 Sender IDs (FCM and GCM).
fcm:no_registration or gcm:no_registration - firebase Default FirebaseApp instance uses a Sender ID from google-services.json. A token will not be requested and sent to Accengage servers. The firebase plugin will still listen messages from the FCM Sender ID but you wont be able to send them via Accengage dashboard since the token wasn't obtained and sent to Accengage servers.
gcm:YOUR_SENDER_ID - push Default GMS InstanceID uses a Sender ID from strings.xml. A token will be sent to Accengage servers. The SDK will listen messages from GCM Sender ID.
gcm:no_registration - push Default GMS InstanceID doesn't uses a Sender ID from strings.xml. A token will not be sent to Accengage servers.

Retrieving Message Parameters

Broadcast Intents

Via Accengage dashboard you can specify some additional parameters for Push, In-App or Inbox messages and retrieve them in the app by a BroadcastReceiver.

The following table describes which broadcast intents contain message parameters:

  Push InApp Inbox
Intent Category com.ad4screen.sdk.intent.category.PUSH_NOTIFICATIONS com.ad4screen.sdk.intent.category.INAPP_NOTIFICATIONS com.ad4screen.sdk.intent.category.INBOX_NOTIFICATIONS
Intent Actions
  • com.ad4screen.sdk.intent.action.DISPLAYED
  • com.ad4screen.sdk.intent.action.CLICKED
  • com.ad4screen.sdk.intent.action.CLOSED
  • com.ad4screen.sdk.intent.action.DISMISSED
  • com.ad4screen.sdk.intent.action.DISPLAYED
  • com.ad4screen.sdk.intent.action.CLICKED
  • com.ad4screen.sdk.intent.action.CLOSED
  • com.ad4screen.sdk.intent.action.DISMISSED
  • com.ad4screen.sdk.intent.action.DISPLAYED
  • com.ad4screen.sdk.intent.action.CLICKED
Parameters
  • Custom Parameters (sent with the action DISPLAYED and CLICKED)

 

  • Display Parameters (sent with the action DISPLAYED)
  • Click Parameters (sent with the action CLICKED)
  • Custom Parameters (sent with the action DISPLAYED and CLICKED)
Screenshot

InApp

BroadcastReceiver Example

 To receive Accengage broadcast intents, add a BroadcastReceiver to your project:

AndroidManifest.xml

<receiver
    android:name="${applicationId}.InAppHandler"
    android:permission="${applicationId}.permission.A4S_SEND">
    <intent-filter>
        <category android:name="com.ad4screen.sdk.intent.category.INAPP_NOTIFICATIONS" />

        // Pick the actions you have interest in from the 4 available :
        <action android:name="com.ad4screen.sdk.intent.action.DISPLAYED" />
        <action android:name="com.ad4screen.sdk.intent.action.CLICKED" />
        <action android:name="com.ad4screen.sdk.intent.action.CLOSED" />
        <action android:name="com.ad4screen.sdk.intent.action.DISMISSED" />
 </intent-filter>
</receiver>

and retrieve your display/click parameters

 

public class InAppHandler extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
                return;
        }

        Set<String> cats = intent.getCategories();
        // Check the category if needed
        if(intent.getCategories().equals(Constants.CATEGORY_INAPP_NOTIFICATIONS)) {
            // Check the action if you need too
            if(intent.getAction().equals(Constants.ACTION_CLICKED)) {
                // And retrieve your parameters below
                String myCustomParam1 = bundle.getString("myKey1");
                String myCustomParam2 = bundle.getString("myKey2");
                ...
            }
        }
    }
}

The url1 is the key of the custom parameter you set in the dashboard, where customParam1 contains its value. 

Retrieving In-App Custom Parameters from callbacks

For In-App messages (Banners and Interstitials) you can also retrieve custom parameters from In-App state callbacks. The following example shows how to retrieve custom display and click parameters from Inflated callback:

@Override
protected void onResume() {
    super.onResume();
    A4S.get(this).startActivity(this); // In case if your activity doesn't extend A4SActivity

    /**
     * This will get triggered when our InApp View is inflated.
     */
    A4S.get(this).setInAppInflatedCallback(new A4S.Callback<InApp>() {

        @Override
        public void onResult(InApp inApp) {
            HashMap<String, String> customParameters = mInApp.getCustomParameters();
            Log.d(TAG, "Custom display parameters: " + customParameters);

            String mUrlSchema1, mUrlSchema2, mInappUrl;
            if (customParameters.containsKey("url1")) {
                mUrlSchema1 = customParameters.get("url1");
            }
            if (customParameters.containsKey("url2")) {
                mUrlSchema2 = customParameters.get("url2");
            }
            if (customParameters.containsKey("acc.display.url")) {
                mInappUrl = customParameters.get("acc.display.url"); // Allows you to retrieve the inApp url adress in case you need it
            }
        }

        @Override
        public void onError(int i, String s) {
            ...
        }
    });
}

You can in the same way retrieve the custom parameters from other InApp states as follow : 

// This will get triggered when our InApp View is ready to be displayed.
A4S.get(this).setInAppReadyCallback(new A4S.Callback<InApp>() {
    ...
});

// This will get triggered when our InApp View has been displayed.
A4S.get(this).setInAppDisplayedCallback(new A4S.Callback<InApp>() {
    ...
});

// This will get triggered when our InApp View had been clicked.
A4S.get(this).setInAppClickedCallback(new A4S.Callback<InApp>() {
    ...
});

// This will get triggered when our InApp View had been closed.
A4S.get(this).setInAppClosedCallback(new A4S.Callback<InApp>() {
    ...
});

This way you're able to access your custom param at every single step of your In-App state callbacks, providing you with a great flexibility.

Push

BroadcastReceiver Example

 To receive Accengage broadcast push intents, add a BroadcastReceiver to your project just like you would do for an InApp:

AndroidManifest.xml

<receiver
    android:name="${applicationId}.PushHandler"
    android:permission="${applicationId}.permission.A4S_SEND">
    <intent-filter>
        // Pick the actions you have interest in from the 4 available :
        <action android:name="com.ad4screen.sdk.intent.action.DISPLAYED" />
        <action android:name="com.ad4screen.sdk.intent.action.CLICKED" />
        <action android:name="com.ad4screen.sdk.intent.action.CLOSED" />
        <action android:name="com.ad4screen.sdk.intent.action.DISMISSED" />

         <category android:name="com.ad4screen.sdk.intent.category.PUSH_NOTIFICATIONS" />
    </intent-filter>
</receiver>

and retrieve your message parameters when the push is opened

Push Handler

public class PushHandler extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
                return;
        }

        //Retrieve your action name like "com.ad4screen.sdk.intent.action.CLICKED"
        String actionName = intent.getAction();

        //Retrieve your parameters below
        String customParam1 = bundle.getString("cp1");
    }
}

The cp1 is the key of the custom parameter you set by the dashboard, where customParam1 contains its value. 

Get Message Parameters from Activity

You also can retrieve your message parameters from your activity

Push Handler

Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey(Constants.EXTRA_GCM_PAYLOAD)) {
    Bundle payload = extras.getBundle(Constants.EXTRA_GCM_PAYLOAD);
    //Retrieve your parameters below
    String customParam1 = payload.getString("parameter");
}

Intercept the push

You can also retrieve your Custom Parameters directly from the Push itself when it's received by the app

First of all you should intercept the GCM push using a custom "GCMHandler".

Then you can add a method to get the intent and receive the custom params

processPush

@Override
protected void processPush(final Context context, final Intent intent) {
    if (A4S.get(context).isAccengagePush(context, intent)) {

        Bundle bundle = intent.getExtras();
        if (customParameters.containsKey("custom_key")) {
            customParameters.get("custom_key"); // Here you retrieve your custom parameter
        }
        //This push belong to A4S
        processA4SPush(context, intent);
    } else {
        //This push must be dispatched elsewhere
        onPushReceive(context, intent);
    }
}

Removing the control panel for Rich Push

To remove the controls (back, forward, reload and open with browser) of the WebView Activity, you need to create a custom layout based on the default one but without the control panel com_ad4screen_sdk_buttonbar. Then on the page editing a push notification you must specify the name of the new layout in the custom parameters.

Below there is an example of the template without the control panel.

my_richpush_without_controls.xml

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

    <RelativeLayout
        android:id="@+id/com_ad4screen_actionbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/com_ad4screen_sdk_actionbar_size"
        android:background="@drawable/com_ad4screen_sdk_actionbar_background_top_holo_dark" >

        <Button
            android:id="@+id/com_ad4screen_sdk_closebutton"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignRight="@+id/com_ad4screen_sdk_logo"
            android:background="@drawable/com_ad4screen_sdk_borderless_button" />

        <ImageView
            android:id="@+id/com_ad4screen_sdk_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:contentDescription="@string/a4s_content_back"
            android:src="@drawable/com_ad4screen_sdk_back_dark" />

        <ImageView
            android:id="@+id/com_ad4screen_sdk_logo"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_centerVertical="true"
            android:layout_marginBottom="8dp"
            android:layout_marginTop="8dp"
            android:layout_toRightOf="@+id/com_ad4screen_sdk_back"
            android:contentDescription="@string/a4s_content_back" />

        <TextView
            android:id="@+id/com_ad4screen_sdk_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_toRightOf="@+id/com_ad4screen_sdk_logo"
            android:maxLines="1"
            android:textColor="@android:color/white"
            android:textSize="18dp" />
    </RelativeLayout>

    <WebView
        android:id="@+id/com_ad4screen_sdk_webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/com_ad4screen_actionbar"
        android:visibility="gone" />

</RelativeLayout>
  1. Add this layout in your Android Studio project 
  2. Specify its name without the file extension .xml on the Settings page in section the RICHPUSH TEMPLATE
  3.  Then choose the name of the template on the page editing a notification

Request Manager Behaviour

Task Flushing Delays

Why ?

In case of an error in sending any request to the APIs, the request will not be lost. Instead it will be saved and we will keep on trying to send it later on to make sure that none of your data is ever lost. The reason is in the event of a problem within the app preventing the request to be successfuly sent. Since we keep on sending the request over and over again, there is a risk of flooding our servers. Therefore we setted up a system that will keep sending the requests at a more reasonable rate as well as keep making sure your data is safe an never lost.

How ?

When the request returns an error, we will stock it and try again in 10 seconds by default. In case the next request fails again, we double this delay meaning we will try sending again in 20 seconds and so forth until we reach 320 seconds or until the request is a success. Please have a look at this pseudo code scheme :

You now understand why in your app's logs you can sometimes find this :

Delays Logs

A4S|DEBUG|RequestManager|Cache will be flushed again in XX secs

JavaScript and WebView

Accengage webview A4SWebView  contains JavaScript interface to be able to handle calls on JavaScript from web pages.  Below there are methods of JavaScript A4S object which you can use to:

A4S Javascript Methods

A4S.trackLead(data)

Tracks a lead event. The  data  is json containing the lead information. For example:

{
    "value":"leadValue",
    "label":"leadLabel"
}

A4S.trackAddToCart(data)

Tracks a cart event. The data is json containing the cart information. For example:

{
    "cartId":"cartId",
    "quantity":1,
    "category":"catItem",
    "label":"labelItem",
    "price":23,
    "articleId":"idItem",
    "currency":"EUR"
}

A4S.trackPurchase(data)

Tracks a purchase. The data is json containing the purchase information. For example:

 {
   "purchaseId":"777",
   "items":[
      {
         "id":"idItem1",
         "quantity":1,
         "category":"cat1",
         "label":"item1",
         "price":23,
         "currency":"EUR"
      },
      {
         "id":"idItem2",
         "quantity":2,
         "category":"cat2",
         "label":"item2",
         "price":50,
         "currency":"EUR"
      }
   ],
   "totalPrice":123,
   "currency":"EUR"
}

A4S.trackEvent(eventId, data)

Tracks an event (lead, cart, purchase or custom event). The eventId is an ID of the event (10 - Lead, 30 - Cart, 50 - Purchase, etc) and the data is either json for lead, cart, purchase or value for custom event.

A4S.setView(view)

Sets a view for the page you would like to target. The view is a view name value.

A4S.updateDeviceInfo(data)

Updates Device Information. The data is json containing fields and its values to update. For example:

{
    "key1":"value1",
    "key2":"value2",
    ...
}

Javascript Injection

When an A4SWebview is started, it will automatically run a javascript file added by Accengage as soon as the page is fully loaded. You can replace this script by your own. For this, set your js URL in ad4_webview_script_url parameter:

strings.xml

<resources>
    <!-- Accengage SDK parameters -->
    ...
    <string name="acc_webview_script_url">http://urlduscript.com/lescript.js</string>
</resources>

Custom WebviewClient

If you want to modify a behaviour of A4SWebview methods, you may use your own WebviewClient :

A4SWebview wv = new A4SWebview();
wv.setWebviewClient(new YourWebViewClient());

Close WebView from WebView's content

You can close the WebView with a specific URL inside the WebView. First, you need to manage the close action.

A4SWebView wv = new A4SWebView(this);
wv.setCloseUrlActionCallback(new Callback<Void>() {

    @Override
    public void onResult(Void result) {
        finish();
    }

    @Override
    public void onError(int error, String errorMessage) {
        // Nothing
    }
});

Next, in your HTML content, add the  bma4sclose  key in the closing URL, for example: http://www.google.com?bma4close=true

JavaScript Sample

For quick tests of A4S methods, check out our simple project on node.js rendering an html page with JavaScript code:

<script>
    function trackLead() {
        var data = "{\"value\":\"leadValue\",\"label\":\"leadLabel\"}";
        A4S.trackLead(data);
    }

    function trackCart() {
        var data = "{\"cartId\":\"cartId\",\n" +
                     "\"quantity\":1,\n" +
                     "\"category\":\"catItem\",\n" +
                     "\"label\":\"labelItem\",\n" +
                     "\"price\":23,\n" +
                     "\"articleId\":\"idItem\",\n" +
                     "\"currency\":\"EUR\"\n}";
        A4S.trackAddToCart(data);
    }

    function trackPurchase() {
        var data = " {\n" +
                   "   \"purchaseId\":\"777\",\n" +
                   "   \"items\":[\n" +
                   "      {\n" +
                   "         \"id\":\"idItem1\",\n" +
                   "         \"quantity\":1,\n" +
                   "         \"category\":\"cat1\",\n" +
                   "         \"label\":\"item1\",\n" +
                   "         \"price\":23,\n" +
                   "         \"currency\":\"EUR\"\n" +
                   "      },\n" +
                   "      {\n" +
                   "         \"id\":\"idItem2\",\n" +
                   "         \"quantity\":2,\n" +
                   "         \"category\":\"cat2\",\n" +
                   "         \"label\":\"item2\",\n" +
                   "         \"price\":50,\n" +
                   "         \"currency\":\"EUR\"\n" +
                   "      }\n" +
                   "   ],\n" +
                   "   \"totalPrice\":123,\n" +
                   "   \"currency\":\"EUR\"\n" +
                   "}";
        A4S.trackPurchase(data);
    }

    function trackEvent() {
        var data = "myCustomEvent";
        A4S.trackEvent(567, data);
    }

    function setView() {
        A4S.setView("PopupPromoActivity");
    }

    function updateDeviceInfo() {
        var data = "{\n" +
                   "    \"firstname\":\"François\",\n" +
                   "    \"lastname\":\"Hollande\"\n" +
                   "}";
        A4S.updateDeviceInfo(data);
    }

</script>

To start the webservice call:

$> node app.js
Node app is running on port 5001

Crash Monitoring

In order to enhance and monitor its quality of service, Accengage has implemented a feature to detect app crashes and quantify any suspicious surge. The goal is for our support to be very reactive in case of any issue affecting our SDKs.

Accengage provides a way to disable this feature if you do not want Accengage to be notified. You need to add additional line to your strings.xml file to disable the crash monitoring by Accengage:

strings.xml

<resources>
    <string name="acc_enable_crashlog">false</string>
</resource>

Workaround for version 3.6.4

If you are using the version 3.6.4 of the SDK (in which the feature was first introduced), we strongly recommend to add a few lines in your AndroidManifest.xml, which will prevent some rare conflicts which may occur.

AndroidManifest.xml

<application
    ...>

    <provider
        android:name="com.ad4screen.sdk.service.modules.crash.CrashLogAppProvider"
        android:authorities="${applicationId}.acccrashappprovider"
        android:exported="false"
        tools:replace="android:authorities"/>
    <provider
        android:name="com.ad4screen.sdk.service.modules.crash.CrashLogSdkProvider"
        android:authorities="${applicationId}.acccrashsdkprovider"
        android:exported="false"
        tools:replace="android:authorities"/>

</application>

Otherwise, you can update directly to version 3.6.4.1 of the SDK, which fixes this rare issue.

Enable Geolocation

By default, the Geolocation is enabled. Just add the following permission above the <application> tag in your AndroidManifest.xml to enable the GPS:

AndroidManifest.xml

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

Disable Geolocation

The permission: “android.permission.ACCESS_FINE_LOCATION” is optional.

If you don't want to use the SDK built-in geolocation or if you prefer updating the location using your own way, please add the following string:

<resources>
    // ...
    <string name="acc_no_geoloc">true</string>
</resource>

As soon as Accengage geolocation is disabled, you can manually update the device's locations using:

getA4S().updateGeolocation(location);

This way, you will be able to use geolocated In-App and Push.

Handling GPS battery consumption

By default, the SDK will always be on and constantly get the users' GPS location. There are two ways you can use to change this behaviour :

Manually updating geolocation

It is possible to permanently disable the geolocation and to update it only when you need it using this method :

getA4S().updateGeolocation(location);

Google Play Services

We strongly encourage you to integrate our Google Play Services Location plugin allowing you to get the geolocation using the most optimised battery consumption. In that way, our SDK will use the FusedLocationProvider in order not to use the GPS when unnecessary. For further explanation, please find the official documentation here.

compile('com.ad4screen.sdk:plugin-play-services-location:4.0.2')

Once the Google Play Services are successfully integrated, you'll be able to define a priority to save battery life vs. diminishing the geolocation accuracy.

You can set a priority to our location plugin:

<resources>
    // ...
    <string name="acc_location_priority">normal</string>
</resource>

Value can be set to: “normal”, “high”, “low” and “none”. This corresponds to the value of the com.google.android.gms.location.LocationRequest setPriority method. Default value is “normal”, which corresponds to PRIORITY_BALANCED_POWER_ACCURACY