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);

Sub Classing Application class

If you need to subclass your Application class (another framework for instance), Accengage SDK provides you with the API to do just that ! You will have to create an application sub-classing your base Application, and add hooks to this new base Application life-cycle methods:

  • onCreate
  • onConfigurationChanged
  • onLowMemory
  • onTerminate

You will be able to use this new application as your base for any Application class in your application. Below is an example of a custom application class :

public class MyApplication extends Application {
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (A4S.isInAccengageProcess(this)) {
            return;
        }
        super.onConfigurationChanged(newConfig);
    }
     
    @Override
    public void onCreate() {
        if (A4S.isInAccengageProcess(this)) {
            return;
        }
        super.onCreate();
    }
     
    @Override
    public void onLowMemory() {
        if (A4S.isInAccengageProcess(this)) {
            return;
        }
        super.onLowMemory();
    }
     
    @Override
    public void onTerminate() {
        if (A4S.isInAccengageProcess(this)) {
            return;
        }
        super.onTerminate();
    }
}

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.

Configure URL Schemes

Deep links are URLs that take users directly to specific content in your app. These URLs are used by Accengage dashboard to specify Push actions and InApp actions. Check out this Android page to get to know more about creating deep links. You may also find this Codelab useful.

Here is an example of declaring two URL schemes testapp://p1 and testapp://p2 in your app

AndroidManifest.xml

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <!-- we are declaring schema testapp://p1 for this activity -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="testapp" android:host="p1" />
        </intent-filter>
    </activity>
    <activity
        android:name="SecondActivity">
        <!— This activity is launched by scheme url testapp://p2 -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="testapp" android:host="p2" />
        </intent-filter>
    </activity>
</application>

If you want, you can retrieve data (custom parameters, for instance) from URL scheme using the code below:

@Override
protected void onResume() {
    super.onResume();
    Intent intent = getIntent();
    if (intent != null && intent.getData() != null) {
        Uri uri = intent.getData(); // parse uri for parameters and display specific data
    }
}

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 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 intercet the FCM push using a custom FirebaseMessagingService.

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);
    }
}

Intercepting Push

At least there are two use cases when you would need to intercept push notification messages:

  • To be able to work with multiple FCM/GCM solutions
  • To manually handle messages

If you use Accengage plugin-firebase-messaging to receive push notifications, you need to add your own FirebaseMessagingService to intercept them.

public class MyMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("MyMessageService", "onMessageReceived from Sender ID: " + remoteMessage.getFrom());
    }
}

Then add the service to AndroidManifest.xml:

<application>

    <service
        android:name=".MyMessagingService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

</application>

When a message is intercepted you need to handle it:

  1. Verify the message type (notification or data message)
  2. For data message, check if it belongs to Accengage
  3. Process Accengage message
public class MyMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.i("MyMessageService", "onMessageReceived from Sender ID: " + remoteMessage.getFrom());

        if (!remoteMessage.getData().isEmpty()) {
            // Data message
            // Handle the message in the main thread of the app process.
            Message messageForHandler = mHandler.obtainMessage();
            messageForHandler.setData(A4S.getPushBundleFromMap(remoteMessage.getData()));
            messageForHandler.sendToTarget();
        } else {
            // Notification message
            String body = "null";
            if (remoteMessage.getNotification() != null) {
                RemoteMessage.Notification notification = remoteMessage.getNotification();
                body = notification.getBody();
            }
            Log.d("MyMessageService", "Notification message: body=" + body);
        }
    }
 
    /**
     * In the case if the app was killed and a new FCM message has been arrived
     * we need to create an instance of A4S in the main thread of the app process.
     */
    private Handler mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message message) {
            A4S a4s = A4S.get(getApplicationContext());
            Bundle bundle = message.getData();
            if (a4s.isAccengagePush(bundle)) {
                // process A4S push
                a4s.handlePushMessage(bundle);
            } else {
                Log.d("MyMessageService", "non Accengage message " + bundle.toString());
                // TODO ... handle non Accengage message
            }
        }
    };
}

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. 

See the User Profile section to find methods of JavaScript A4S object.

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.

Geolocation

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.

implementation 'com.ad4screen.sdk:plugin-play-services-location:4.1.9'

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