package com.malcom.library.android.module.core; import java.util.Hashtable; import java.util.Properties; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; import android.widget.LinearLayout; import com.malcom.library.android.MCMDefines; import com.malcom.library.android.exceptions.ConfigModuleNotInitializedException; import com.malcom.library.android.exceptions.CoreNotInitializedException; import com.malcom.library.android.module.ad.MCMAdAdapter; import com.malcom.library.android.module.ad.MCMAdEventHandler; import com.malcom.library.android.module.campaign.MCMCampaignAdapter; import com.malcom.library.android.module.campaign.MCMCampaignDTO; import com.malcom.library.android.module.campaign.MCMCampaignNotifiedDelegate; import com.malcom.library.android.module.config.MCMConfigManager; import com.malcom.library.android.module.notifications.EnvironmentType; import com.malcom.library.android.module.notifications.MCMNotificationModule; import com.malcom.library.android.module.stats.MCMStats; import com.malcom.library.android.module.stats.Subbeacon.SubbeaconType; /** * Malcom Android Library Core Module. * * NOTE * * Malcom Android Library needs the following permissions: * * <pre> * <uses-permission android:name="android.permission.INTERNET" /> * <uses-permission android:name="android.permission.READ_PHONE_STATE" /> * <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> * <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> * <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> * <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> * </pre> * * Please, see documentation on https://github.com/MyMalcom/malcom-lib-android/ for more information. * * @author Malcom Ventures, S.L. * @since 2012 */ public class MCMCoreAdapter { // This constant should be changed when upgrading the project version in POM (How can we take it from there?) public static final String SDK_VERSION = "2.0.11"; public static final String MALCOM_LIBRARY_PREFERENCES_FILE_NAME = "com.malcom.library.android"; public static final String PROPERTIES_MALCOM_BASEURL = "MalcomBaseURL"; public static final String PROPERTIES_MALCOM_ADWHIRL_URL = "AdWhirlBaseUrl"; public static final String PROPERTIES_MALCOM_APPID = "MalcomAppId"; public static final String PROPERTIES_MALCOM_APPSECRETKEY = "MalcomAppSecretKey"; public static final String PROPERTIES_MALCOM_ADWHIRLID = "adWhirlId"; public static final String PROPERTIES_MALCOM_GCM_SENDERID = "gcmSenderId"; public static final String PROPERTIES_MALCOM_APP_NAME = "adAppName"; public static final String PROPERTIES_MALCOM_COMPANY_NAME = "adCompanyName"; private static final String MALCOM_CONFIG = "MCM_MALCOM_CONFIG"; private Context context = null; public static final int CONNECTION_DEFAULT_TIMEOUT = 3000; // 3 sgs. public static final int CONNECTION_DEFAULT_DATA_RECEIVAL_TIMEOUT = 2000; // 2 sgs. public static String SERVER_URL = null; private static MCMCoreAdapter instance = null; private static Properties properties; private static boolean coreInitialized = false; public static String applicationPackage = null; // Ads module: size banner variables public int adWidth = 320; public int adHeight = 52; protected MCMCoreAdapter() { // Exists only to defeat instantiation. } public static MCMCoreAdapter getInstance() { if(instance == null) { instance = new MCMCoreAdapter(); } return instance; } /** * * @param key * @return */ public String coreGetProperty(String key) { String result = ""; if (coreInitialized) { SharedPreferences prefs = this.context.getSharedPreferences( MALCOM_CONFIG, 0); result = prefs.getString(key, ""); } if (result.equals("")) { Log.e(MCMDefines.LOG_TAG, "You should call first initMalcom with the appId and secretKey"); } return result; } /** * Required. Initialize the Malcom Android LIbrary. * * @param uuid * @param secretKey */ public void initMalcom(Context context, String uuid, String secretKey) { Log.d(MCMDefines.LOG_TAG, "initMalcom uuid: "+uuid+" secretKey: "+secretKey); this.context = context; SharedPreferences prefs = context.getSharedPreferences(MALCOM_CONFIG, 0); prefs.edit().putString(PROPERTIES_MALCOM_APPID, uuid).commit(); prefs.edit().putString(PROPERTIES_MALCOM_APPSECRETKEY, secretKey).commit(); prefs.edit().putString(PROPERTIES_MALCOM_BASEURL, MCMDefines.MALCOM_BASEURL).commit(); prefs.edit().putString(PROPERTIES_MALCOM_ADWHIRL_URL, MCMDefines.MALCOM_ADWHIRL_URL).commit(); MCMCoreAdapter.applicationPackage = context.getPackageName(); coreInitialized = true; } /** * Gets the android device unique id. * * @param context * @return */ public String coreGetDeviceId(Context context){ return MCMNotificationModule.getInstance().gcmGetDeviceUdid(context); } // MODULES : // --- CONFIGURATION /** * This method calls to the configuration module of the library loading the data and executing the config * if is needed by the "execute" param. * * @param activity Activity. * @throws CoreNotInitializedException */ public void moduleConfigurationActivate(Activity activity) throws CoreNotInitializedException{ if (coreInitialized) { MCMConfigManager.getInstance().createConfig(activity, applicationPackage); } else { Log.e("CORE", "Core has not been initialized, use initMalcom method."); } } /** * This method resturn the value of the specified configuration property. When using this method the configuration * module should already loaded by using "useConfigModule()" method. * * @param key Property * @return The property value or null if the specified property does not exist or if the property is null * @throws CoreNotInitializedException * @throws ConfigModuleNotInitializedException * @deprecated Use moduleConfigurationGerProperty(String key, ConfigListener listener) instead. */ public String moduleConfigurationGetProperty(String key) throws CoreNotInitializedException, ConfigModuleNotInitializedException{ if(coreInitialized) if(MCMConfigManager.getInstance().isConfigurationLoaded()){ return MCMConfigManager.getInstance().getKeyValue(key); }else{ //TODO: Pedro - Cargamos el fichero de configuraciĆ³n y cuando termina llamamos al callback con el if(MCMConfigManager.getInstance().isConfigurationLoading()) throw new ConfigModuleNotInitializedException("Config module is being initialized, wait until is fully initialized before call this method."); else throw new ConfigModuleNotInitializedException("Config module has not been initialized, use useConfigModule()."); } else throw new CoreNotInitializedException("Core has not been initialized, use initMalcom method."); } /** * This method resturn the value of the specified configuration property. When using this method the configuration * module should already loaded by using "useConfigModule()" method. * * @param key Property * @return The property value or null if the specified property does not exist or if the property is null * @throws CoreNotInitializedException * @throws ConfigModuleNotInitializedException */ public void moduleConfigurationGetProperty(String key, ConfigListener listener) throws CoreNotInitializedException, ConfigModuleNotInitializedException{ if(coreInitialized) MCMConfigManager.getInstance().getProperty(key,listener); else throw new CoreNotInitializedException("Core has not been initialized, use initMalcom method."); } /** * This method resturn the value of the specified configuration property. When using this method the configuration * module should already loaded by using "useConfigModule()" method. * * @param key Property * @return The property value or null if the specified property does not exist or if the property is null * @throws ConfigModuleNotInitializedException * @deprecated Use moduleConfigurationGerProperty(String key, ConfigListener listener) instead. */ public String moduleConfigurationGetProperty(Activity context, String key) throws ConfigModuleNotInitializedException{ return moduleConfigurationGetProperty(key); } /** * Tells if the configuration module is correctly initialized. * * @return * @throws CoreNotInitializedException */ public boolean moduleConfigurationIsModuleInitialized() throws CoreNotInitializedException{ return MCMConfigManager.getInstance().isConfigurationLoaded(); } public String SDKVersion() { return SDK_VERSION; } public interface ConfigListener { public void onReceivedParameter(String parameter, String value); } // --- BEACONS & SUB-BEACONS /** * Starts the beacon processing. * * @param context * @param useLocation Set to TRUE to also store location data in the beacon. */ public void moduleStatsStartBeacon(Context context, boolean useLocation){ MCMStats.initAndStartBeacon(context, properties, useLocation); } /** * Starts a sub-beacon(event) processing with the given name. * * @param beaconName Name of the sub-beacon (event) */ public void moduleStatsStartBeaconWithName(String beaconName){ moduleStatsStartBeaconWithName(beaconName, true); } /** * Starts a sub-beacon(event) processing with the given name. * * @param beaconName Name of the sub-beacon (event) * @param trackSession */ public void moduleStatsStartBeaconWithName(String beaconName, boolean trackSession){ if(coreInitialized){ try{ MCMStats.getSharedInstance().startSubBeaconWithName(beaconName, SubbeaconType.CUSTOM, new Hashtable<String, Object>(), trackSession); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error initializing sub-beacon(event) with name '"+beaconName+"' ("+e.getMessage()+")"); } }else{ throw new CoreNotInitializedException("Stats has not been initialized, use moduleStatsStartBeacon()."); } } /** * Starts a sub-beacon(event) processing with the given name and params. * * @param beaconName Name of the sub-beacon (event) * @param params SubBeacon parameters */ public void moduleStatsStartBeaconWithName(String beaconName, Hashtable<String, Object> params){ if(coreInitialized){ try{ MCMStats.getSharedInstance().startSubBeaconWithName(beaconName, SubbeaconType.CUSTOM, params, false); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error initializing sub-beacon(event) with name '"+beaconName+"' ("+e.getMessage()+")"); } }else{ throw new CoreNotInitializedException("Stats has not been initialized, use moduleStatsStartBeacon()."); } } /** * Starts a sub-beacon(event) processing with the given name and params. * * @param beaconName Name of the sub-beacon (event) * @param params SubBeacon parameters * @param trackSession */ public void moduleStatsStartBeaconWithName(String beaconName, boolean trackSession, Hashtable<String, Object> params){ if(coreInitialized){ try{ MCMStats.getSharedInstance().startSubBeaconWithName(beaconName, SubbeaconType.CUSTOM, params, trackSession); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error initializing sub-beacon(event) with name '"+beaconName+"' ("+e.getMessage()+")"); } }else{ throw new CoreNotInitializedException("Stats has not been initialized, use moduleStatsStartBeacon()."); } } /** * Starts a sub-beacon(event) to identify the user app. * * @param name Name of the user app * @param mail mail of the user app */ public void moduleStatsIdentifyUser(String name, String mail){ moduleStatsIdentifyUser(name, mail, new Hashtable<String, Object>()); } /** * Starts a sub-beacon(event) to identify the user app. * * @param name Name of the user app * @param mail mail of the user app * @param params SubBeacon parameters with optional additional info */ public void moduleStatsIdentifyUser(String name, String mail, Hashtable<String, Object> params){ if(coreInitialized){ try{ //generates the hashtable for user info Hashtable<String, Object> userHashtable = new Hashtable<String, Object>(); userHashtable.put("name", name); userHashtable.put("mail", mail); userHashtable.putAll(params); MCMStats.getSharedInstance().startSubBeaconWithName("app_user", SubbeaconType.SPECIAL, userHashtable, false); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error initializing sub-beacon(event) with name '"+"app_user"+"' ("+e.getMessage()+")"); }catch (Exception e) { e.printStackTrace(); } }else{ throw new CoreNotInitializedException("Stats has not been initialized, use moduleStatsStartBeacon()."); } } /** * Starts a sub-beacon(event) to identify a revenue. * * @param name Name of product * @param SKU Code of product * @param price Price of the single product * @param currencyCode International code for currency (EUR, USD) * @param amount Total purchase amount */ public void moduleStatsRegisterRevenue(String name, String SKU, float price, String currencyCode, int amount){ if(coreInitialized){ try{ Hashtable<String, Object> revenueHashtable = new Hashtable<String, Object>(); revenueHashtable.put("name", name); revenueHashtable.put("SKU", SKU); revenueHashtable.put("price", String.valueOf(price)); revenueHashtable.put("currencyCode", currencyCode); revenueHashtable.put("amount", String.valueOf(amount)); MCMStats.getSharedInstance().startSubBeaconWithName("revenue", SubbeaconType.SPECIAL, revenueHashtable, false); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error initializing sub-beacon(event) with name '"+"app_user"+"' ("+e.getMessage()+")"); }catch (Exception e) { e.printStackTrace(); } }else{ throw new CoreNotInitializedException("Stats has not been initialized, use moduleStatsStartBeacon()."); } } /** * Stop the beacon processing and send the resulting beacon data to Malcom. */ public void moduleStatsEndBeacon(){ try { MCMStats.getSharedInstance().stopBeacon(); } catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error stopping beacons ("+e.getMessage()+")"); } } /** * Sub-beacons(events) are automatically stopped when general beacon stats are stopped but, optionally, * a sub-beacon(event) can be stopped with this method. */ public void moduleStatsEndBeaconWithName(String beaconName){ try{ MCMStats.getSharedInstance().endSubBeaconWithName(beaconName); }catch(MCMStats.BeaconException e){ Log.e("CORE-STATS", "Error stopping sub-beacon(event) with name '"+beaconName+"': ("+e.getMessage()+")"); } } public void moduleStatsAddTag(String tag) { try { MCMStats.getSharedInstance().addTag(tag); } catch (MCMStats.BeaconException e) { // TODO Auto-generated catch block Log.e("CORE-STATS", "Error add tag': ("+e.getMessage()+")"); } } public void moduleStatsRemoveTag(String tag) { try { MCMStats.getSharedInstance().removeTag(tag); } catch (MCMStats.BeaconException e) { // TODO Auto-generated catch block Log.e("CORE-STATS", "Error remove tag': ("+e.getMessage()+")"); } } public void moduleStatsSetUserMetadata(String userMetadata) { try { MCMStats.getSharedInstance().setUserMetadata(userMetadata); } catch (MCMStats.BeaconException e) { // TODO Auto-generated catch block Log.e("CORE-STATS", "Error set user metadata': ("+e.getMessage()+")"); } } public String moduleStatsGetUserMetadata() { String userMetadata = null; try { userMetadata = MCMStats.getSharedInstance().getUserMetadata(); } catch (MCMStats.BeaconException e) { // TODO Auto-generated catch block Log.e("CORE-STATS", "Error get user metadata': ("+e.getMessage()+")"); } return userMetadata; } // --- ADS /** * * @param context * @param layoutAd * @param eventHandler * @deprecated use Malcom's campaigns module instead. */ public void moduleAdsActivate(Activity context, LinearLayout layoutAd, MCMAdEventHandler eventHandler){ MCMAdAdapter.getInstance().createAds(context, layoutAd, (String)properties.get(PROPERTIES_MALCOM_ADWHIRLID), eventHandler, adWidth, adHeight); } /** * * @param context * @param layoutAd * @deprecated use Malcom's campaigns module instead. */ public void moduleAdsActivate(Activity context, String adsID, LinearLayout layoutAd){ MCMAdAdapter.getInstance().createAds(context, layoutAd, adsID, adWidth, adHeight); } // --- NOTIFICATIONS public void setSenderId(String senderId) { SharedPreferences prefs = context.getSharedPreferences( MALCOM_CONFIG, 0); prefs.edit().putString(PROPERTIES_MALCOM_GCM_SENDERID, senderId).commit(); } /** * Registers the device with GCM and Malcom push notification system. * * NOTE: * The environment is set by looking for the application debug mode, * if is set to TRUE, the environment will be SANDBOX, otherwise PRODUCTION. * * @param context * @param title Title for the notification * @param clazz Class to call when clicking in the notification */ public void moduleNotificationsRegister(Context context, String title, Class<?> clazz){ MCMNotificationModule.getInstance().gcmRegisterDevice(context.getApplicationContext(), title, clazz); } /** * Registers the device with GCM and Malcom push notification system. * * @param context * @param environment Destination environment. See @ENvironmentType. * @param title Title for the notification * @param clazz Class to call when clicking in the notification */ public void moduleNotificationsRegister(Context context, EnvironmentType environment, String title, Class<?> clazz){ MCMNotificationModule.getInstance().gcmRegisterDevice(context, environment, title, clazz); } /** * Un-registers the device from GCM and from Malcom. * * @param context */ public void moduleNotificationsUnregister(Context context){ MCMNotificationModule.getInstance().gcmUnregisterDevice(context.getApplicationContext()); } /** * Gets the notification registration token or null if the device is not registered. * * @param context * @return */ public String moduleNotificationsGetRegistrationToken(Context context){ return MCMNotificationModule.getInstance().gcmGetRegistrationToken(context); } // Campaings /** * Method that adds the cross selling campaign to the specified activity. * @param activity where the banner will be placed * @param duration indicating the time that is going to be shown the banner in seconds (0 for always visible). * @param delegate delegate for handling the performing of the banners * @param loadingImgResId image that will be displayed while the campaign image is being downloaded */ public void moduleCampaignAddCrossSelling(Activity activity, int duration, MCMCampaignNotifiedDelegate delegate, Integer loadingImgResId) { MCMCampaignAdapter.getInstance(MCMCampaignDTO.CampaignType.IN_APP_CROSS_SELLING) .addBanner(activity, MCMCampaignDTO.CampaignType.IN_APP_CROSS_SELLING, duration, delegate, loadingImgResId); } /** * Method that requests all the available cross selling campaigns for the app and calls the receiver * with the banner views to let the developer places them * @param activity the context where the request is made * @param receiver the interface that will be called with the retrieved data */ public void moduleCampaignRequestCrossSelling(Activity activity, MCMCampaignAdapter.RequestCampaignReceiver receiver) { MCMCampaignAdapter.getInstance(MCMCampaignDTO.CampaignType.IN_APP_CROSS_SELLING) .requestBanner(activity, MCMCampaignDTO.CampaignType.IN_APP_CROSS_SELLING, receiver); } /** * Method that adds the promotions campaign to the specified activity. By default, campaigns will last 15 seconds. * @param activity where the banner will be placed * @param duration indicating the time that is going to be shown the banner in seconds (0 for always visible). * @param delegate delegate for handling the performing of the banners * @param loadingImgResId image that will be displayed while the campaign image is being downloaded */ public void moduleCampaignAddPromotion(Activity activity, int duration, MCMCampaignNotifiedDelegate delegate, Integer loadingImgResId) { MCMCampaignAdapter.getInstance(MCMCampaignDTO.CampaignType.IN_APP_PROMOTION) .addBanner(activity, MCMCampaignDTO.CampaignType.IN_APP_PROMOTION, duration, delegate, loadingImgResId); } /** * Method that requests all the available cross selling campaigns for the app and calls the receiver * with the banner views to let the developer places them * @param activity the context where the request is made * @param receiver the interface that will be called with the retrieved data */ public void moduleCampaignRequestPromotion(Activity activity, MCMCampaignAdapter.RequestCampaignReceiver receiver) { MCMCampaignAdapter.getInstance(MCMCampaignDTO.CampaignType.IN_APP_PROMOTION) .requestBanner(activity, MCMCampaignDTO.CampaignType.IN_APP_PROMOTION, receiver); } /** * Method that add an RateMyApp alert based on the server params * @param activity where the alert will be shown * @param delegate for handle the campaign behaviour */ public void moduleCampaignAddRateMyApp(Activity activity, MCMCampaignNotifiedDelegate delegate) { MCMCampaignAdapter.getInstance(MCMCampaignDTO.CampaignType.IN_APP_RATE_MY_APP) .addRateAlert(activity, delegate); } }