/*******************************************************************************
Copyright (c) 2014,2015, Oracle and/or its affiliates. All rights reserved.
$revision_history$
10-nov-2014 Steven Davelaar
1.0 initial creation
******************************************************************************/
package oracle.ateam.sample.mobile.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import oracle.adf.model.datacontrols.device.DeviceManager;
import oracle.adf.model.datacontrols.device.DeviceManagerFactory;
import oracle.adf.model.datacontrols.device.Location;
import oracle.adfmf.framework.api.AdfmfContainerUtilities;
import oracle.adfmf.framework.api.JSONBeanSerializationHelper;
import oracle.ateam.sample.mobile.Version;
import oracle.ateam.sample.mobile.controller.bean.ConnectivityBean;
import oracle.ateam.sample.mobile.v2.persistence.metadata.PersistenceConfig;
import oracle.maf.api.dc.ws.rest.RestServiceAdapter;
/**
* Class used to track the mobile app usage. In mobile-persistence-config, two endpoints can be configured: one to register
* the start of an application, and one to register when an error occurs while incoking some REST service.
* A-Team uses this internally to track Oracle internal apps, but customers can use the same facility by simply
* changing the endpoints in persistence config.
* Tracking is switched on/off through propety tracking.enabled=true/false in mobile-persistence-config.
*/
public class UsageTracker
{
private static ADFMobileLogger sLog = ADFMobileLogger.createLogger(UsageTracker.class);
private static Location location;
private boolean locationInit = true;
private final static String CONNECTION_END_POINT = "https://adc-ofm0187-gse.oracledemos.com/store";
private final static String START_URI = "/applications/starts";
private final static String ERROR_URI = "/applications/errors";
public UsageTracker()
{
super();
}
protected boolean isOffline()
{
return new ConnectivityBean().isOffline();
}
protected String getCurrentDateTime()
{
String pattern = "yyyy-MM-dd HH:mm:ss Z";
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String sdate = sdf.format(now);
return sdate;
}
protected String getCurrentTimeZone()
{
String pattern = "zzzz";
Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String sdate = sdf.format(now);
return sdate;
}
protected Location getLocation()
{
if (locationInit)
{
locationInit = false;
DeviceManager dmgr = DeviceManagerFactory.getDeviceManager();
// if (dmgr.getOs().equalsIgnoreCase("ios")){
try
{
// increase max age and disable high accuracy so position gets computed much faster
// for example, in buildings with large wifi networks (like oracle offices)
// this.currentLocation = dmgr.getCurrentPosition(6000, true);
location = dmgr.getCurrentPosition(600000, false);
}
catch (Exception e)
{
// cur pos not available, van happen in Android simulator
sLog.severe("Cannot determine current location: " + e.getLocalizedMessage());
}
}
return location;
}
protected boolean isUseLocation()
{
String useLoc = PersistenceConfig.getPropertyValue("tracking.use.location");
return "true".equalsIgnoreCase(useLoc);
// if (useLoc!=null)
// {
// return "true".equalsIgnoreCase(useLoc);
// }
// return true;
}
protected Map<String,Object> getBasePayload()
{
// device info
String networkStatus = DeviceManagerFactory.getDeviceManager().getNetworkStatus();
String model = DeviceManagerFactory.getDeviceManager().getModel(); // iPad Simulator x86_64
String os = DeviceManagerFactory.getDeviceManager().getOs(); // iOS
String version = DeviceManagerFactory.getDeviceManager().getVersion(); // 7.1
String platform = DeviceManagerFactory.getDeviceManager().getPlatform(); // iPad Simulator
// app info
String appId = AdfmfContainerUtilities.getApplicationInformation().getId();
String appVendor = AdfmfContainerUtilities.getApplicationInformation().getVendor();
String appVersion = AdfmfContainerUtilities.getApplicationInformation().getVersion();
Map<String,Object> payload = new HashMap<String,Object>();
payload.put("appId", appId);
payload.put("appVersion", appVersion);
String appstoreAppId = PersistenceConfig.getPropertyValue("tracking.appstore.appid");
if (appstoreAppId != null)
{
payload.put("appStoreAppId", appstoreAppId);
}
payload.put("os", os);
payload.put("osVersion", version);
payload.put("model", model);
payload.put("network", networkStatus);
payload.put("ampaVersion", Version.VERSION);
payload.put("timeZone", getCurrentTimeZone());
if (isUseLocation())
{
Location loc = getLocation();
if (loc != null)
{
Map<String,String> locMap = new HashMap<String,String>();
payload.put("location", locMap);
locMap.put("lat", loc.getLatitude() + "");
locMap.put("lng", loc.getLongitude() + "");
}
}
return payload;
}
protected void sendMessage(String connectionEndPoint, String uri,Map payload)
{
try
{
String json = JSONBeanSerializationHelper.toJSON(payload).toString();
RestServiceAdapter rsa = new NoConnRestServiceAdapterImpl(connectionEndPoint);
rsa.clearRequestProperties();
rsa.addRequestProperty("Content-Type", "application/json");
rsa.setRequestMethod(RestServiceAdapter.REQUEST_TYPE_POST);
rsa.setRequestURI(uri);
rsa.send(json);
}
catch (Exception e)
{
sLog.severe("Error invoking tracking start resource: " + e.getLocalizedMessage());
}
}
protected String getConnectionEndPoint()
{
String trackingConnection = PersistenceConfig.getPropertyValue("tracking.connection.endpoint");
return trackingConnection!=null ? trackingConnection : CONNECTION_END_POINT;
}
protected String getStartUri()
{
String startUri = PersistenceConfig.getPropertyValue("tracking.start.uri");
return startUri!=null ? startUri : START_URI;
}
protected String getErrorUri()
{
String errorUri = PersistenceConfig.getPropertyValue("tracking.error.uri");
return errorUri!=null ? errorUri : ERROR_URI;
}
protected boolean isTrackingEnabled()
{
String trackingEnabled = PersistenceConfig.getPropertyValue("tracking.enabled");
return "true".equalsIgnoreCase(trackingEnabled);
}
public void registerStartAppMessage()
{
if (!isTrackingEnabled())
{
return;
}
final String connectionEndPoint = getConnectionEndPoint();
final String trackingStartUri = getStartUri();
if (connectionEndPoint == null || trackingStartUri == null || isOffline())
{
return;
}
// send message in background thread so we don't delay app start-up
Runnable runnable = new Runnable()
{
public void run()
{
Map payload = getBasePayload();
payload.put("startTime", getCurrentDateTime());
sendMessage(connectionEndPoint, trackingStartUri,payload);
}
};
Thread thread = new Thread(runnable);
thread.start();
}
public void registerErrorMessage(final String message)
{
if (!isTrackingEnabled())
{
return;
}
final String connectionEndPoint = getConnectionEndPoint();
final String trackingErrorUri = getErrorUri();
if (connectionEndPoint == null || trackingErrorUri == null || isOffline())
{
return;
}
// send message in background thread so we don't delay app start-up
Runnable runnable = new Runnable()
{
public void run()
{
Map payload = getBasePayload();
payload.put("errorTime", getCurrentDateTime());
payload.put("errorMessage", message);
sendMessage(connectionEndPoint, trackingErrorUri,payload);
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}