npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

fanmeter-sdk-reactnative

v3.1.0

Published

Pluggable's Fanmeter for React Native apps

Downloads

105

Readme

Pluggable's Fanmeter Plugin for React Native apps

Fanmeter's React Native plugin for React Native apps. This plugins allows you to create fanmeter events. You have two ways of doing it:

  1. You want everything automated and, so, you'll need to integrate with FCM to handle the received notifications that start the event (see the next section and you'll need to use the fanmeterExecute API);

  2. You want to handle the conditions yourself (without Fanmeter's notifications). You can skip the next section (the Pre-conditions one) and start calling the fanmeterStartService and fanmeterStopService API.

Nonetheless, note that for Android, push permission is required so that a notification is shown to the user so that he knows that a foreground service is running. Also, note that the GPS permission is needed for the fans to participate in the geo-restricted events.

Hence, you need to ask for such permission in Android. For iOS, add the Background Modes capability and enable Location Updates. Also, you must open your Info.plist file and add something the following code at the bottom: <key>NSLocationAlwaysUsageDescription</key> <string>GPS is required to collect data to classify your celebration during the event! </string> <key>NSLocationWhenInUseUsageDescription</key> <string>GPS is required to collect data to classify your celebration during the event! </string>

Note that, for Android only, Fanmeter is required to use a Data Sync foreground service to communicate non-intrusive sensor motion data with Pluggable's server. Since API 34 of Android, when publishing an app that uses such services, you are required to fill a Policy Declaration where you must justify the need for such services. In Fanmeter's case, when filling such policy, you will be asked the question "What tasks require your app to use the FOREGROUND_SERVICE_DATA_SYNC permission?".

There, you should:

  1. Select the option OTHER in Other tasks;
  2. Provide the following video link:
    https://youtu.be/w4d7Pgksok0
  3. Provide the following description:
    Fanmeter is an Android SDK, incorporated in this app, that uses a Data Sync foreground service to communicate non-intrusive sensor motion data with Pluggable's servers, which are used to quantify the engagement of the user in real-time. The foreground service must start as soons as the user opts to participate in the event (so that it can collect and communicate motion data) and must keep running until the user himself decides to terminate his/her participation.

Pre-conditions [Integrate with FCM]

Before using this plugin, if you want a fully-automate experience, you should guarantee that your app already integrates with React Native Firebase and then with Firebase Cloud Messaging (FCM). The steps are as follows:

  1. Create a new Firebase project. Note that current versions of firebase-ios-sdk have a minimum Xcode requirement of 14.1, which implies a minimum macOS version of 12.5 (macOS Monterey);

  2. Install the React Native Firebase "app" module to the root of the React Native project with NPM: npm install --save @react-native-firebase/app. The @react-native-firebase/app module must be installed before using any other Firebase service;

  3. Android Setup - a configuration file must be downloaded and added to the project:

    • On the Firebase console, add a new Android application and enter the projects details. The "Android package name" must match the local projects package name which can be found inside of the manifest tag within the /android/app/src/main/AndroidManifest.xml file within the project;
    • Download the google-services.json file and place it inside of the project at the following location: /android/app/google-services.json;
    • To allow Firebase on Android to use the credentials, the google-services plugin must be enabled on the project. This requires modification to two files in the Android directory. First, add the google-services plugin as a dependency inside of the /android/build.gradle file:
    buildscript {
        dependencies {
            // ... other dependencies
            classpath 'com.google.gms:google-services:4.3.15'
        }
    }
    • Lastly, execute the plugin by adding the following to the /android/app/build.gradle file:
    apply plugin: 'com.android.application'
    apply plugin: 'com.google.gms.google-services' // <- Add this line 
  4. iOS Setup - to allow the iOS app to securely connect to the Firebase project, a configuration file must be downloaded and added to the project, and you must enable frameworks in CocoaPods:

    • On the Firebase console, add a new iOS application and enter your projects details. The "Apple bundle ID" must match your local project bundle ID. The bundle ID can be found within the "General" tab when opening the project with Xcode;
    • Download the GoogleService-Info.plist file;
    • Using Xcode, open the projects /ios/{projectName}.xcodeproj file (or /ios/{projectName}.xcworkspace if using Pods) and right click on the project name and "Add files" to the project. Select the downloaded GoogleService-Info.plist file from your computer, and ensure the Copy items if needed checkbox is enabled;
    • To allow Firebase on iOS to use the credentials, the Firebase iOS SDK must be configured during the bootstrap phase of your application. To do this, open your /ios/{projectName}/AppDelegate.mm file (or AppDelegate.m if on older react-native), and add the following:
    #import "AppDelegate.h"
    #import <Firebase.h> // <- Add this line
    // ...
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Add me --- \/
        [FIRApp configure]; // <- Add this line
        // Add me --- /\
        // ...
    }
    // ...
    • Beginning with firebase-ios-sdk v9+ (react-native-firebase v15+) you must tell CocoaPods to use frameworks. Open the file ./ios/Podfile and add the following line inside your targets (right after the line calling the react native Podfile function to get the native modules config):
    target 'reactnativeapp' do
    config = use_native_modules!
    use_frameworks! :linkage => :static # <- Add this line
    $RNFirebaseAsStaticFramework = true # <- Add this line (see next point)
    ...
    # Note that if you have use_frameworks! enabled, Flipper will not work and
    # you should disable the next line.
    #:flipper_configuration => flipper_config, # <- COMMENT this line
    ...
    • To use Static Frameworks on iOS, you also need to manually enable this for the project with the following global to your ./ios/Podfile file:
    # right after `use_frameworks! :linkage => :static`
    $RNFirebaseAsStaticFramework = true
  5. Once the above steps have been completed, the React Native Firebase library must be linked to the project and the application needs to be rebuilt. Users on React Native 0.60+ automatically have access to "autolinking", requiring no further manual installation steps. To automatically link the package, rebuild your project (for manual linking, if you're using an older version of React Native without autolinking support, or wish to integrate into an existing project, you can follow the manual installation steps for iOS and Android):

    # Android apps
    npm run android
    
    # iOS apps
    cd ios/
    pod install --repo-update
    cd ..
    npm run ios
  6. You can now install the messaging module by running:

    # Install the messaging module
    npm install @react-native-firebase/messaging
    
    # If you're developing your app using iOS, run this command
    cd ios/ && pod install
    
    cd ..
    npm run ios
  7. iOS Setup - iOS requires further configuration before you can start receiving and sending messages through Firebase. Read the documentation and follow the steps on how to setup iOS with Firebase Cloud Messaging.

NOTE: FCM via APNs does not work on iOS Simulators. To receive messages & notifications a real device is required. The same is recommended for Android. Also, for iOS, React-Native-Firebase uses use_frameworks, which has compatibility issues with Flipper, Hermes, and Fabric.

NOTE 2: In iOS foreground notification are not displayed. If it is needed you can use a package for local notifications.

Fanmeter Usage

Pre-conditions

  1. After configuring your app to integrate with FCM, you are ready to use this plugin to properly engage with your fans! To install the Fanmeter Package just run in the root of the project:
    npm install fanmeter-sdk-reactnative

Note that for Android, to customize the used notification icon just add the desired icon in the Android's drawable folder and name it ic_push_app_icon. Otherwise, a default icon, not related to your app, will be used.

  1. Once the above steps have been completed, the React Native Firebase library must be linked to your project and your application needs to be rebuilt. Users on React Native 0.60+ automatically have access to "autolinking", requiring no further manual installation steps. To automatically link the package, rebuild your project:

    # Android apps
    npm run android
    
    # iOS apps
    cd ios/
    pod install --repo-update
  2. OPTIONAL: For iOS, if you want to display push notifications while your app is in the foreground, you must allow that specific scenario:

    • In your app's AppDelegate.h file:
    // Import the native iOS UserNotifications package
    #import <UserNotifications/UserNotifications.h> // <- Add this line
    
    // Extend the UNUserNotificationCenterDelegate class
    @interface AppDelegate : RCTAppDelegate<UNUserNotificationCenterDelegate> // <- Update this line
    • In your app's AppDelegate.mm file:
    // Import the native iOS UserNotifications package
    #import <UserNotifications/UserNotifications.h> // <- Add this line
    
    // ...
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // ...
        [UNUserNotificationCenter currentNotificationCenter].delegate = self; // <- Add this line
        // ...
    }
       
    // ...
    
    // Function to implement to display foreground push notifications
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
        completionHandler(UNNotificationPresentationOptionAlert|UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound);
    }

Fully-automated Fanmeter

If you want to automate the entire process, this library exposes two mandatory methods, which can be imported and used in your .tsx files as demonstrated in the next lines.

  • The fanmeterExecute method is used to launch the SDK as soon as a notification is tapped by the user. The fanmeterExecuteWithLocalNotification method is used to tell the SDK to launch a local notification to the user, which is required by Android to launch push notifications when the app is in the foreground. Both accept the same set of parameters:

    • externalUserId, the user identifier in the company's db - can be the username, the uuid, or other;
    • externalTokenId, the individual smartphone identifier (allows for same accounts in different devices);
    • notificationData, a map containing data coming from the notification;
    • externalUserEmail, the user's email (optional);
    • fcmToken, the FCM token id (mandatory for autonomous events);
    • ticketNumber, the ticket number of the user (optional);
    • ticketStand, the stand where the given user is (optional);
    • notificationClassResponse, the name of the class that is being instantiated when the user clicks the notification - example: "com.company.activities.SearchActivity" (null opens a default view);;
    • log, enables additional logging (optional).

    It also returns the following values:

    • 1: SUCCESS;
    • -80: No GPS/PUSH Permissions; -81: GPS Disabled; -82: Invalid event coordinates;
    • -92: Invalid License; -93: Invalid Event; -94: Invalid event dates; -95: externalUserId or externalTokenId are empty; -96: Failed to get event details; -97: Failed to start background service.

    These should be called as follows:

    import { 
        fanmeterExecute,
        fanmeterExecuteWithLocalNotification,
        ...
    } from 'fanmeter-sdk-reactnative';
    const EXTERNAL_USER_ID: string = 'your_user_id';
    const EXTERNAL_TOKEN_ID: string = 'the_id_of_the_device';
    const EXTERNAL_USER_EMAIL: string | null = '[email protected]';
    const FCM_TOKEN: string | null = 'the_fcm_token';
    const TICKET_NUMBER: string | null = 't-1234';
    const TICKET_STAND: string | null = null;
    const NOTIFICATION_CLASS_RESPONSE: string | null = null;
    const FANMETER_LOG: boolean | null = true;
    
    const COMPANY_NAME: string = 'your_company_name';
    const LICENSE_KEY: string = 'your_company_key';
    // To listen to messages in the foreground, call the onMessage method inside of your application code. 
    // Code executed via this handler has access to React context.
    useEffect(() => {
    messaging().onMessage(async remoteMessage => {
        const notificationData = remoteMessage.data as {[key: string]: any};
        delete notificationData['fcm_options']; // 'fcm_options' must be removed - it is a dict!
        fanmeterExecuteWithLocalNotification(
            EXTERNAL_USER_ID,
            EXTERNAL_TOKEN_ID,
            notificationData,
            EXTERNAL_USER_EMAIL,
            FCM_TOKEN,
            TICKET_NUMBER,
            TICKET_STAND,
            NOTIFICATION_CLASS_RESPONSE,
            FANMETER_LOG
        ).then(setExecuteWithLocalNotification);
    });
    }, []);
    
    useEffect(() => {
        // When the application is opened from a quit state, check whether an initial notification is available:
        messaging().getInitialNotification().then(remoteMessage => {
            if (remoteMessage) {
                const notificationData = remoteMessage.data as {[key: string]: any};
                delete notificationData['fcm_options']; // 'fcm_options' must be removed - it is a dict!
                fanmeterExecute(
                    EXTERNAL_USER_ID,
                    EXTERNAL_TOKEN_ID,
                    notificationData,
                    EXTERNAL_USER_EMAIL,
                    FCM_TOKEN,
                    TICKET_NUMBER,
                    TICKET_STAND,
                    NOTIFICATION_CLASS_RESPONSE,
                    FANMETER_LOG
                ).then(setExecute);
            }
        });
        // When the application is running, but in the background:
        messaging().onNotificationOpenedApp(remoteMessage => {
            const notificationData = remoteMessage.data as {[key: string]: any};
            delete notificationData['fcm_options']; // 'fcm_options' must be removed - it is a dict!
            fanmeterExecute(
                EXTERNAL_USER_ID,
                EXTERNAL_TOKEN_ID,
                notificationData,
                EXTERNAL_USER_EMAIL,
                FCM_TOKEN,
                TICKET_NUMBER,
                TICKET_STAND,
                NOTIFICATION_CLASS_RESPONSE,
                FANMETER_LOG
            ).then(setExecute);
        });
    }, []);
  • Also, the fanmeterLaunchFanmeterView method is used to tell the SDK to launch the Fanmeter native view. For example, it can be associated with a button in the company's app, redirecting the user to the Fanmeter native view, allowing users without notification permissions to participate in the event. It will open the Fanmeter view with the event with the closest date to the current date, accepting a set of parameters, including:

    • companyName, the name of the company requesting to start the service;
    • licenseKey, the company key requesting to start the service;
    • externalUserId, the user identifier in the company's db - can be the username, the uuid, or other;
    • externalTokenId, the individual smartphone identifier (allows for same accounts in different devices);
    • externalUserEmail, the user's email (optional);
    • fcmToken, the FCM token id (mandatory for fully autonomous events);
    • ticketNumber, the ticket number of the user (optional);
    • ticketStand, the stand where the given user is (optional);
    • log, enables additional logging (optional).

    It also returns the following values:

    • 1: SUCCESS;
    • -80: No GPS/PUSH Permissions; -81: GPS Disabled; -82: Invalid event coordinates;
    • -92: Invalid License; -93: Invalid Event; -94: Invalid event dates; -95: externalUserId or externalTokenId are empty; -96: Failed to get event details; -97: Failed to start background service.
    async function launchFanmeterViewSDK() {
        fanmeterLaunchFanmeterView(
            COMPANY_NAME,
            LICENSE_KEY,
            EXTERNAL_USER_ID,
            EXTERNAL_TOKEN_ID,
            EXTERNAL_USER_EMAIL,
            FCM_TOKEN,
            TICKET_NUMBER,
            TICKET_STAND,
            FANMETER_LOG
        ).then(setLaunch);
    }
  • You also need to know the FCM token ID associated with each user device. It's equally mandatory to subscribe the user to a specific topic so that they can receive event notifications:

    // Get user's FCM token. 
    messaging().getToken().then(token => {
        console.log('TOKEN is:', token);
        FCM_TOKEN = token;
    });
    // Listen to whether the token changes
    messaging().onTokenRefresh(token => {
        console.log('TOKEN refreshed to:', token);
        FCM_TOKEN = token;
    });
    
    // Subscribe to specific topic.
    messaging().subscribeToTopic('fanmeter_reactnative_topic').then(() => console.log('Subscribed to topic!'));

OWN-UI Fanmeter

If you want to integrate Fanmeter in your own UI, you can use the fanmeterStartService, fanmeterStopService, and fanmeterIsServiceRunning methods. These methods are exposed by the library to handle user sensor data collection during an event and can be used, if needed, as follows.

  • You should call the fanmeterStartService method to let the SDK enable sensor data collection for your client's device during a particular event. It accepts a set of parameters, including:

    • companyName, the name of the company requesting to start the service;
    • licenseKey, the license key of the company requesting to start the service;
    • eventTitle, the event name;
    • externalUserId, the user identifier in the company's db - can be the username, the uuid, or other;
    • externalTokenId, the individual smartphone identifier (allows for same accounts in different devices);
    • externalUserEmail, the user's email (optional);
    • fcmToken, the FCM token id (optional);
    • ticketNumber, the ticket number of the user (optional);
    • ticketStand, the stand where the given user is (optional);
    • notificationClassResponse, he name of the class that is being instantiated when the user clicks the notification - example: "com.pluggableai.activities.SearchActivity" (optional);
    • log, enables additional logging (optional).

    It also returns the following values:

    • 1: SUCCESS;
    • -80: No GPS/PUSH Permissions; -81: GPS Disabled; -82: Invalid event coordinates;
    • -92: Invalid License; -93: Invalid Event; -94: Invalid event dates; -95: externalUserId or externalTokenId are empty; -96: Failed to get event details; -97: Failed to start background service.
    async function startExecuteSDK() {
        fanmeterStartService(
            COMPANY_NAME,
            LICENSE_KEY,
            "eventTitle",
            EXTERNAL_USER_ID,
            EXTERNAL_TOKEN_ID,
            EXTERNAL_USER_EMAIL,
            FCM_TOKEN,
            TICKET_NUMBER,
            TICKET_STAND,
            NOTIFICATION_CLASS_RESPONSE,
            FANMETER_LOG
        ).then(setstartService);
    }
  • You should call the fanmeterStopService method to let the SDK disable sensor data collection for your client's device during a particular event. This returns 1, if success, otherwise an error code. For that, you must do as follows:

    async function stopExecuteSDK() {
        fanmeterStopService(
            FANMETER_LOG
        ).then(setstopService);
    }
  • The method fanmeterIsServiceRunning is used to check the current status of the service. This returns 1, if the service is running, otherwise 0.

    async function checkServiceStatusSDK() {
        fanmeterIsServiceRunning().then(setIsRunning);
    }

Generics

Other important methods are to request user permission to be able to send notifications and request GPS permission. Also, get the user token and listen for changes to get the user FCM_TOKEN and update it when it changes.

More info

  • For full compatibility, attention to the used versions of XCODE, SWIFT and COCOAPODS. Recommended versions are XCODE=15, SWIFT=5.9, and COCOAPODS=1.14.2.

  • For more info visit https://pluggableai.xyz/ or give us feedback to [email protected].