Titanium
Use the Xtremepush SDK to integrate your Titanium apps with the platform
With the Xtremepush module for Titanium, you can add Xtremepush to both iOS and Android apps quickly.
Make sure your mobile apps are added to Xtremepush, following the guides for Android and iOS.
Add the Xtremepush Titanium files
Download the Titanium module from the Titanium SDK releases page.
Copy the modules folder from the download into the directory shown below for your respective system, and allow it to merge.
~/Library/Application Support/Titanium
C:\ProgramData\Titanium
~/.titanium
Modify the tiapp.xml
tiapp.xml
Import the Xtremepush module into your project by opening your project's tiapp.xml
in TitaniumStudio. You can add the module via the TiApp editor UI by clicking the green add button next to the list of modules,
and selecting Xtremepush from the drop down list
you will see Xtremepush in the list of modules if you have successfully added it.
You can also add the module by editing tiapp.xml
via the raw XML editor.
Note: For android apps, due to Xtremepush's dependency on play-services, you will also need to add the ti.playservices module, in the same way you added the Xtremepush module outlined above.
iOS
<modules>
...
<module platform="android">com.xtremepush.xtremepush</module>
<module platform="iphone">com.xtremepush.xtremepush</module>
</modules>
You must follow the steps under Add description for CoreBluetooth in the Integrate the iOS SDK guide, to add the required CoreBluetooth description.
If you are also enabling push notifications, you will need to set up your Apple push certificates and add the notifications handling methods described in the iOS push notifications guide.
If you are adding adding location services, you will need to add the usage descriptions by following the iOS location permissions guide. If you are using beacons you will also need to add the bluetooth usage message described in the beacons section in the same guide.
Additionally you will need to add the bluetooth flag to your register.json
in the iOS node:
ios: {
locationsEnabled: true,
beaconsEnabled: true,
},
Android
Follow the steps in the guide for Android push notifications to get the configuration values and google-services.json
file.
In native android, or another framework that uses the gradle build tool you can add a plugin which automatically migrates values from the google-services.json file to the app resources. Titanium requires the configuration values to be manually set from the configuration file.
In your project, edit the file platform/android/res/values/values.xml
, creating it if it does not already exist:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<! -- Present in all applications -->
<string name="google_app_id" translatable="false">1:312123...:android:...</string>
<! -- Present in applications with the appropriate services configured
<string name="gcm_defaultSenderId" translatable="false">312123...</string>
<string name="default_web_client_id" translatable="false">312123...-860....apps.googleusercontent.com</string>
<string name="google_api_key" translatable="false">AIza..</string>
<string name="project_id" translatable="false">my_project...</string>
...
</resources>
The values for the keys in the XML can be found in the google-services.json
file in these locations:
XML key | Location in google-services.json |
---|---|
google_app_id | {YOUR_CLIENT}/client_info/mobilesdk_app_id |
gcm_defaultSenderId | project_info/project_number |
default_web_client_id | {YOUR_CLIENT}/oauth_client/client_id (client_type == 3) |
ga_trackingId | {YOUR_CLIENT}/services/analytics-service/analytics_property/tracking_id |
firebase_database_url | project_info/firebase_url |
google_api_key | {YOUR_CLIENT}/api_key/current_key |
google_crash_reporting_api_key | {YOUR_CLIENT}/api_key/current_key |
project_id | project_info/project_id |
Now you add the Xtremepush module and ti.playservices
to your app:
Edit the tiapp.xml
file to add the following to the android section:
<android xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<manifest>
<uses-sdk android:targetSdkVersion="26"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- REQUIRED for XtremePush -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- REQUIRED PERMISSIONS for GCM (Push Notifications) -->
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- GCM requires a Google account. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<!-- This app has permission to register with GCM and receive message -->
<permission android:name=".permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name=".permission.C2D_MESSAGE"/>
<!-- The two elements above ensure that only this application can receive the messages and registration result -->
<!-- OPTIONAL XtremePush settings-->
<!-- REQUIRED FOR GEO-LOCATION-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- REQUIRED FOR IBEACON -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<!-- REQUIRED IF you support iBeacon and your app must support devices that don't support BLE -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false"/>
<application>
<activity android:configChanges="orientation|screenSize"
android:label="@string/title_activity_inbox"
android:name="ie.imobile.extremepush.ui.InboxActivity" android:theme="@style/Theme.Transparent"/>
<activity android:exported="false"
android:name="ie.imobile.extremepush.ui.OnclickPushActivity" android:taskAffinity=""/>
<service android:name="ie.imobile.extremepush.NotificationOnClickHandlerService"/>
<activity android:exported="false" android:name="ie.imobile.extremepush.ui.WebViewActivity"/>
<activity android:exported="false"
android:label="Locations are not available"
android:name="ie.imobile.extremepush.ui.LocationDialogActivity" android:theme="@android:style/Theme.Dialog"/>
<!-- REQUIRED FOR GEO LOCATION SERVICES -->
<service android:name="ie.imobile.extremepush.location.GeoLocationService"/>
<!-- REQUIRED FOR IBEACON -->
<service android:enabled="true" android:exported="false" android:isolatedProcess="false" android:label="beacon" android:name="org.altbeacon.beacon.service.BeaconService"/>
<service android:enabled="true" android:exported="false" android:name="org.altbeacon.beacon.BeaconIntentProcessor"/>
<service android:name="ie.imobile.extremepush.beacons.BeaconLocationService"/>
<!-- REQUIRED FOR GCM, LOCATION AND BEACON -->
<receiver android:name="ie.imobile.extremepush.receivers.CoreBroadcastReceiver">
<intent-filter>
<action android:name="ie.imobile.extremepush.BEACON_SERVICE_STARTED"/>
<category android:name="."/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
<service
android:name="ie.imobile.extremepush.beacons.XPBeaconJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
<service
android:name="ie.imobile.extremepush.util.ImageHandlerJobService" android:permission="android.permission.BIND_JOB_SERVICE"/>
<receiver android:exported="true" android:name="ie.imobile.extremepush.beacons.BeaconLocationReceiver"/>
<receiver android:exported="true" android:name="ie.imobile.extremepush.location.GeoLocationBroadcastReceiver"/>
<receiver android:exported="true" android:name="ie.imobile.extremepush.location.ProxymityAlertReceiver"/>
<receiver android:name="ie.imobile.extremepush.receivers.XP_App_Update_Receiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<category android:name="."/>
</intent-filter>
</receiver>
<service android:name="ie.imobile.extremepush.google.XPFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="com.google.firebase.components.ComponentDiscoveryService">
<meta-data android:name="com.google.firebase.components:com.google.firebase.iid.Registrar" android:value="com.google.firebase.components.ComponentRegistrar"/>
</service>
</application>
</manifest>
</android>
Enable in Alloy application
If you are using Alloy, then you would add the following to your alloy.js
file:
// Initialise XtremePush
Ti.Network.registerApp;
Alloy.Globals.xtremepush = require("com.xtremepush.xtremepush");
Alloy.Globals.xtremepush.registerApp(
{
appKey: "YOUR_APP_KEY",
debugLogsEnabled: true,
impressionsBatchingEnabled: true,
impressionsStoreLimit: 999,
inappMessagingEnabled: true,
inboxBadgeCallback: inboxBadgeCallbackFunction,
inboxEnabled: true,
messageResponseCallback: messageResponseCallbackFunction,
deeplinkCallback: onDeeplinkReceived,
tagsBatchingEnabled: true,
tagsStoreLimit: 888,
startSessionEnabled: true,
sessionsStoreLimit: 777,
attributionsEnabled: true,
foregroundNotificationsEnabled: true,
ios: {
//if using location
locationsEnabled: true,
//if sandbox
sandboxModeEnabled: true
},
android: {
gcmProjectNumber: "YOUR_GCM_PROJECT_NUMBER",
//if using geo
geoEnabled: false,
//if using beacon
beaconsEnabled: true
}
});
You can see in the registration above there are three callback functions (messageResponseCallback
, InboxBadgeCallback
, deeplinkCallback
). Examples of how to use these is shown later.
In your controller JavaScript file index.js
you need to register the app with the Xtremepush servers:
Ti.Network.registerForPushNotifications;
Because of Titanium's handling of Windows and TabGroups as activities in Android, there are a number of additional options which can be set in your index.js
file. In this example, $.index
is the app's main TabGroup and $.b1-14
are example buttons which show some of the options available in the module.
Ti.Network.registerForPushNotifications;
var handlePush = function(exampleDataForProcessing) {
// Handle received push data
alert(exampleDataForProcessing);
};
var handlePushList = function(data) {
// Handle received push data
var pushArray = data.notifications;
for (var i=0; i < pushArray.length; i++)
{
Ti.API.debug(pushArray[i]);
handlePush(pushArray[i].alert);
}
};
$.button0.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the trigger event button");
Alloy.Globals.xtremepush.hitEvent("InAppCampaign");
});
$.button1.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the hit tag button");
Alloy.Globals.xtremepush.hitEvent("tagTest");
});
$.button2.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the hit impression button");
Alloy.Globals.xtremepush.hitImpression("ExampleImpression");
});
$.button3.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the release all button");
Alloy.Globals.xtremepush.sendTags();
Alloy.Globals.xtremepush.sendImpressions();
});
batching = false;
$.button4.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the toggle batching button");
batching = !batching;
Ti.API.debug(batching);
Alloy.Globals.xtremepush.setTagsBatchingEnabled(batching);
Alloy.Globals.xtremepush.setImpressionsBatchingEnabled(batching);
});
$.button5.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the getPushList button");
Alloy.Globals.xtremepush.getPushNotifications({
success: handlePushList,
offset: 0,
limit: 1,
read: 0
});
});
$.button6.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the markRead button");
Alloy.Globals.xtremepush.markPushAsRead($.pushid.value);
});
$.button7.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the openInbox button");
Alloy.Globals.xtremepush.openInbox();
});
$.button8.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the Report Message Clicked button with lastPushId = " + lastPushId);
Alloy.Globals.xtremepush.reportMessageClicked(lastPushId);
});
$.button9.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the Report Message Clicked button with lastPushId = " + lastPushId +" and action 'test'");
var obj = {id: lastPushId, action: "test"};
Alloy.Globals.xtremepush.reportMessageClicked(obj);
});
$.button10.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the Report Message Dismissed button with lastPushId = "+lastPushId);
Alloy.Globals.xtremepush.reportMessageDismissed(lastPushId);
});
$.button11.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the Show Notification button");
Alloy.Globals.xtremepush.showNotification(lastPushId);
});
$.button12.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the set External Id button");
Alloy.Globals.xtremepush.setExternalId($.pushid.value);
});
$.button13.addEventListener('click', function(e) {
Titanium.API.debug("You clicked the set Hit Event With Value button");
var stringOrHash = {0: "number0", 1: "number1"};
//var stringOrHash = "numbers";
var obj = {title: "tagString", value: stringOrHash};
Alloy.Globals.xtremepush.hitEventWithValue(obj);
});
// Declare XtremePush in alloy.js as shown here:
// Alloy.Globals.xtremepush = require("com.xtremepush.xtremepush");
var OS_ANDROID = Ti.Platform.getOsname() === "android";
if (OS_ANDROID) {
var onRotation = function(e){
var rotation = false;
switch(e.orientation) {
case Ti.UI.LANDSCAPE_RIGHT:
Ti.API.info("LANDSCAPE_RIGHT");
rotation = true;
break;
case Ti.UI.LANDSCAPE_LEFT:
Ti.API.info("LANDSCAPE_LEFT");
rotation = true;
break;
case Ti.UI.UPSIDE_PORTRAIT:
Ti.API.info("UPSIDE_PORTRAIT");
rotation = true;
break;
case Ti.UI.PORTRAIT:
Ti.API.info("PORTRAIT");
rotation = true;
break;
default:
Ti.API.info("Unknown!!");
}
if(rotation)
Alloy.Globals.xtremepush.onRotation();
};
$.index.orientationModes = [
Titanium.UI.PORTRAIT,
Titanium.UI.UPSIDE_PORTRAIT,
Titanium.UI.LANDSCAPE_LEFT,
Titanium.UI.LANDSCAPE_RIGHT
];
Ti.Gesture.addEventListener('orientationchange', onRotation);
}
$.index.open();
Make sure you set the user ID
It is recommended that at this stage you use our SDK method to set user IDs by following our dedicated guide to ensure devices can be associated and targeted in your campaigns by your own unique identifier.
Setting Notification Icon in Android
There is a key that can be set in register.json
called setIcon
. If set, the program will attempt to find and use iconfilenamewithoutextension.png
in the platform/android/res/drawable
directory and will also search for a color entry with the same name in any of the XML files in the platform/android/res/values
directory to use as a background colour behind the icon.
setIcon: "iconFileNameWithoutExtension",
Android encourages you to set an icon that is in-keeping with their design guidelines. Further information ca be found in the guide for Android notification icons.
Xtremepush callback functions
messageResponseCallback
, deeplinkCallback
, and inboxBadgeCallback
are JavaScript functions defined in a JavaScript file of your project. After creating, you have to define them in the registerXtremePush
function:
messageResponseCallback: messageResponseCallbackFunction,
inboxBadgeCallback: inboxBadgeCallbackFunction,
deeplinkCallback: onDeeplinkReceived,
messageResponseCallback
var messageResponseCallbackFunction = function(xp) {
if(xp.response.type === "present"){
alert("receive");
} else if (xp.response.type === "click"){
alert("click");
} else if (xp.response.type === "dismiss"){
alert("dismiss");
}
};
The response.type
variable shown above can be one of specific values:
- present - when a push notification is received and the app is in the foreground
- click - when a message is clicked
- dismiss - when a message is dismissed
Below is a complete example of custom notification handling, which:
- shows a custom dialog when a push message is received in foreground,
- opens an article page when a message is clicked,
- saves information when one of the message buttons is clicked.
(Each message sent in the campaigns associated with the example, include a custom payload for articleId
)
var messageResponseCallbackFunction = function(xp) {
Ti.API.info(''+JSON.stringify(xp));
if (xp.response.type === "present") {
openArticle(xp.message.articleId);
//when the user clicks on a message
} else if (xp.response.type === "click") {
//default click action
if (!xp.response.hasOwnProperty('action')) {
openArticle(xp.message.articleId);
//action for specific button click
} else {
if (xp.response.action === "like") {
likeArticle(xp.message.articleId);
} else if (xp.response.action === "share") {
shareArticle(xp.message.articleId);
}
}
//show alert if dismiss button click
} else if (xp.response.type === "dismiss") {
alert("message dismiss");
}
};
inboxBadgeCallback
This is called when the badge number updates. The badge number is checked when:
- new push message arrives
- application is started
- inbox window is closed
var inboxBadgeCallbackFunction = function(xp) {
//do something with message
alert('Inbox badge update with number: ' + JSON.stringify(xp));
};
deeplinkCallback
This is called when a message with the click action Go to deeplink is clicked.
var onDeeplinkReceived = function(xp) {
alert('onDeeplinkReceived called in alloy.js with data:'+JSON.stringify(xp));
};
Foreground notification handling
It is important to define the correct behaviour for the situation when a push notification is received in foreground. You don't want to interrupt the user workflow, but still be delivering important information to the user.
The default behaviour on both iOS and Android is to show OS style notification. But this can be changed, by adding the payload with key foreground
and value false
to your campaign.
Now when the push is received, should the app be in the foreground, the notification will not be displayed.
If you wish to change the default behaviour to not show notifications when app is open, in the register function you can use the following:
foregroundNotificationsEnabled: false
Retrieving your Xtremepush ID
Now that your app is configured for mobile analytics and sending push notifications the final basic feature of Xtremepush is retrieving your Xtremepush ID. This can be accomplished by calling the deviceInfo
method:
Alloy.Globals.xtremepush.deviceInfo
This method returns your device's ID as obtained from Xtremepush server. If your device has not received an ID then it has not successfully registered and there is an issue with your integration. If for example you want to quickly output the the device ID to the debug area in TitaniumStudio you would use it like this:
Ti.API.debug("deviceInfo" + Alloy.Globals.xtremepush.deviceInfo);
If you successfully retrieve the ID it can be used to identify your device on the platform and to send a push notification to just that device.
User management
Set primary user on platform:
Alloy.Globals.xtremepush.setUser("");
Set temporary user on platform:
Alloy.Globals.xtremepush.setTempUser("");
Updated almost 3 years ago