Giter Club home page Giter Club logo

countly-sdk-react-native's Introduction

This SDK has been sunsetted. This repo has been archived and will not be maintained anymore. Please use React Native (bridge) SDK instead: https://github.com/Countly/countly-sdk-react-native-bridge

What's Countly?

Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.

About this SDK

This repository includes the Countly React Native SDK. See Countly React Native SDK documentation for installation.

Other Github resources

This SDK needs one of the following Countly Editions to work:

For more information about Countly Enterprise Edition, see comparison of different Countly Editions

There are also other Countly SDK repositories (both official and community supported) on Countly Resources.

How can I help you with your efforts?

Glad you asked. We need ideas, feedbacks and constructive comments. All your suggestions will be taken care with upmost importance. We are on Twitter and Facebook if you would like to keep up with our fast progress!

Badges

If you like Countly, why not use one of our badges and give a link back to us, so others know about this wonderful platform?

Countly - Product Analytics

<a href="https://count.ly/f/badge" rel="nofollow"><img style="width:145px;height:60px" src="https://count.ly/badges/dark.svg" alt="Countly - Product Analytics" /></a>

Countly - Product Analytics

<a href="https://count.ly/f/badge" rel="nofollow"><img style="width:145px;height:60px" src="https://count.ly/badges/light.svg" alt="Countly - Product Analytics" /></a>

Support

Have any questions? Visit http://community.count.ly.

countly-sdk-react-native's People

Contributors

arturskadikis avatar gorkem-cetin avatar jeffsteinmetz avatar nodexpertsdev avatar nxvinay avatar richeterre avatar sercanov avatar shashanksingh234 avatar trinisofttechnologies avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

countly-sdk-react-native's Issues

Mixed user profiles when using the same device

Hello,

I have an issue when using different account on the same physical phone.
My 2 User Profiles are merged.
There is only one profile with both email, both name etc.
I use the stop session in the log out & the start session in the log in.

When I used Countly in an iOS Native project I had the option to use this :
Countly.sharedInstance().userLoggedOut();

Is there the same option on React Native ?
What can I do to resolve my issue and having distinct user profile ?

Thanks in advance

SDK should allow the client to determine logic for Data only messages - current assumption on all data only messages is they are to be displayed.

Description:
The countly react-native-sdk makes an assumption that all data only messages via the OnMessage() handler should be displayed, and that they came from countly.

To be on par with the native SDK, see, for example, how the Android SDK handles OnMessage.
OnMessage is handled in the client, and uses a display helper in the Countly SDK.
The Android native Countly SDK looks for a title and message in the data payload, if they don't exist, the display helper returns null.

see:

https://github.com/Countly/countly-sdk-android/blob/5e89ee1b1cfd60381bb4cadd734ee6c86780f87c/sdk-messaging-fcm/src/main/java/ly/count/android/sdk/messaging/CountlyPush.java#L359

https://github.com/Countly/countly-sdk-android/blob/5e89ee1b1cfd60381bb4cadd734ee6c86780f87c/sdk-messaging-fcm/src/main/java/ly/count/android/sdk/messaging/CountlyPush.java#L327

and
https://github.com/Countly/countly-sdk-android/blob/1b7d6b964908908dfa41e44248b799a33264670b/app-messaging-fcm/src/main/java/ly/count/android/demo/messaging_fcm/DemoFirebaseMessagingService.java#L32

https://github.com/Countly/countly-sdk-android/blob/1b7d6b964908908dfa41e44248b799a33264670b/app-messaging-fcm/src/main/java/ly/count/android/demo/messaging_fcm/DemoFirebaseMessagingService.java#L90

It looks like the OnMessage handler is in the client app (not the SDK), and there is a CountlyPush.displayMessage helper in the SDK to display the notification.
If it is not a notification from the countly “Message” ui, it falls back to returning null, which means the client application should handle the silent push data.
Or, the data message came from another push service and should be handled and displayed gracefully by the client app, not the Countly SDK.

Unused parameter in Countly.init

The Countly.init function has an (undocumented) parameter DEVICE_ID:

Countly.init = function(ROOT_URL, APP_KEY, DEVICE_ID) {

Other than passing this parameter recursively, it does not appear to be used within the body of Countly.init:

Countly.init = function(ROOT_URL, APP_KEY, DEVICE_ID) {
    if (!Countly.isReady) {
        return setTimeout(function() {
            Countly.init(ROOT_URL, APP_KEY, DEVICE_ID);
        }, 1000);
    };
    Countly.isInit = true;
    Countly.ROOT_URL = ROOT_URL;
    Countly.APP_KEY = APP_KEY;
    Ajax.setItem("DEVICE_ID", Countly.DEVICE_ID);
    Ajax.get("/i", {}, function(result) {
        Countly.update();
    });

};

Deeplink not working with iOS implementation

As per Sercan:

On block below, it calls this.deepLinkHandler.handler1 with notificationOpen.action but .action value is
“com.apple.UNNotificationDefaultActionIdentifier”, deep link url is in notificationOpen.notification._data.c.l

this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
const action = notificationOpen.action;
if (this.deepLinkHandler.handler1){
this.deepLinkHandler.handler1(action);
}
const notification: Notification = notificationOpen.notification;

console.log(“onNotificationOpened”, notification);
console.log(notification._notificationId);
this.openPush(notification._notificationId);

});

Unable to capture native exceptions on Android

When I was testing crash logging for native exceptions on Android, I've run into a situation where the exception handler was being properly called, but the crash log report would never make it to the server.

I believe that the issue is in the get call for the crash report:

    // this.log('GET Method', newData);
    const newURL = `${this.ROOT_URL}${url}?${Ajax.query(newData)}`;
    Ajax.get(newURL, newData, callback).then((response) => {
      this.log('promise resolved', response);
    }).catch((error) => {
      this.add(newURL, newData);
      this.log('Promise reject', error);
    });

I believe that the Ajax.get call starts, but then the main Activity is killed in response to the native exception. Since the catch handler never runs, the crash log data is never added to the queue, and so never gets sent to the server.

Is there any way to synchronously add the crash log data to the offline queue, so at least it will be reported the next time the app is executed?

Separate crash reporting from alerting

For our application, we will want to customize the alerts displayed to the user when a fatal JS or native exception occurs. At the moment, the Countly.addCrashLog method:

  1. uploads a crash log
  2. displays an alert
  3. restarts the RN app

Can this be refactored a bit so that the crash log uploading (1) is separable, and we can implement our own custom alert/restart code?

temporary ID generation could work like other SDKs, with less chance of collision

instead of Ajax.id, use a UUID as a function or local class method which has less chance of collision
see the countly web sdk:

https://github.com/Countly/countly-sdk-web/blob/2f7e4ffbd5b17a7422a7a9bcfb2830d299f69572/lib/countly.js#L1282

  generateUUID () {
    var d = new Date().getTime()
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0
        d = Math.floor(d / 16)
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
    })
  }

UNUserNotificationCenter undefined in Appdelegate.m

The instructions at:
https://resources.count.ly/docs/react-native

suggest addeding:

[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];

and

-(void) userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
 [[RNFirebaseMessaging instance] didReceiveRemoteNotification:response.notification.request.content.userInfo];
 completionHandler();
}

This fails the build, UNUserNotificationCenter is an undefined Type.

Backgrounding app artificially inflates session duration by value of SESSION_DURATION

The way that the app state change is handled, it fires a session_stop event when backgrounding the app, if you bring the app to the foreground it sends a subsequent session_start event.

If you do this during the time defined in SESSION_DURATION (default: 60 seconds), it seems like the count.ly servers consider this the same session (this is good). However when viewing the dashboard I observer the session_stop event has increased the "duration" of the session by 60 seconds.

I guess you can see where I am going here, and this may be only an issue with the UI of count.ly rather than this SDK. If I sit there and constantly background and foreground the app my session duration goes through the roof.

Example: I took this screenshot at 15:38 however the session started at 15:37 is already 17 minutes long.

image

Asynchronous initialization should return a Promise

Currently, the initialization for the Countly module runs like this:

  • On import, DEVICE_ID is retrieved from AsyncStorage, and that callback sets Countly.isReady:
Ajax.getItem("DEVICE_ID", function(err, S_DEVICE_ID) {
    Countly.isReady = true;
    Countly.DEVICE_ID = S_DEVICE_ID || Ajax.id();
});
  • When Countly.init() is called, it either runs immediately (if the above callback has completed), or keeps scheduling itself to be called again every 1 Hz until it succeeds.

  • Countly.start() will silently fail if the Countly.init() call has not yet succeeded.

Because of this hidden asynchronous wait, if init() and start() are called in sequence (as in the sample code from https://resources.count.ly/docs/react-native#section-sdk-usage):

Countly.init("https://try.count.ly","app_key");

// start session	
Countly.start();

the start() call will silently fail in the general case.

Since the initialization is inherently asynchronous, a better pattern for Countly.init would be to:

  • Kick off the read of DEVICE_ID from AsyncStorage.
  • When the Promise from AsyncStorage.getItem resolves successfully, then finish the rest of the state initialization.
  • Return a Promise that is resolved when the whole initialization is complete.

Then the calling code can wait for the Countly.init Promise to be resolved before trying to start the session.

Also, the SDK documentation should be updated to show this asynchronous step.

SDK meta data

App crashes if onMessage is handled when the app is in the background

How to reproduce:

in index.js include

AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => Countly.bgMessaging);

Create a default channel id of fcm_default_channel and register in ComponentDidMount() such as
(this channel step may or may not be necessary to reproduce the issue).

    // For android only --start
    if (Platform.OS === 'android') {
      const channel = new firebase.notifications.Android.Channel('fcm_default_channel', 'Example', firebase.notifications.Android.Importance.Max)
                .setDescription('Example Notifications');
      firebase.notifications().android.createChannel(channel);
    }
    // For android only --END
    Countly.initMessaging(Countly.PRODUCTION,'fcm_default_channel');

in the Android mainifest, include

<service android:name="io.invertase.firebase.messaging.RNFirebaseBackgroundMessagingService" />

Ensure foreground messages are displayed when sending from Countly, or a firebase curl command such as:

curl -X "POST" "https://fcm.googleapis.com/fcm/send" \
  -H "Authorization: key=<SERVER-KEY>" \
  -H "Content-Type: application/json" \
  -d $'{
    "data": {
      "message": "Testing with direct FCM API",
      "title": "Test Message",
      "sound": "default"
  },
  "android_channel_id" : "fcm_default_channel",
  "to": "<FIREBASE-DEVICE-TOKEN>"
}'

With the app still running, place the application in the background, sending the same message will cause an exception, and the React-Native app will crash.
The debugger captures a log as follows:

android_emulator_-_nexus_5x_api_28_x86_5554_and_react_native_debugger

Offline queue only sent on init

The initial release of 2.0 empties the queue only on Countly.init.

If an app is left in the background, the queue will not be sent since init will typically only be called when the app starts.

Other SDK approaches have a more frequent retry approach.

setNewDeviceID:onServer equivalent for React Native SDK

Other Countly SDKs (ex. iOS) have a capability to merge existing old device ID data on server. This is useful when changing from tracking by device ID to tracking by a custom user ID.

Can you implement a similar method for this React Native SDK? Something analogous to setNewDeviceID:onServer from the iOS SDK, or the convenience methods userLoggedIn and userLoggedOut.

Add bgMessaging in documents

This line must added at the end of index.js. This line is important for basckground Push notifications.
Please add is Docs
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => Countly.bgMessaging);

Event Log show failed timestamp on iOS

Hii I have the problem on iOS device, on event log always show failed timestamp.

{ "sum": 0, "dur": 0, "segmentation": { "id": 1234567890, }, "hour": 12, "key": "coba_apa_ya", "timestamp": -2147483648, "dow": 4, "count": 1 }

this result timestamp :
GMT: Friday, December 13, 1901 8:45:52 PM
Your time zone: Saturday, December 14, 1901 3:45:52 AM GMT+07:00

Symbolication support

We need symbolication support for React Native SDK so that crashes sent from devices are more human readable.

Incorrect call arguments for enabling crash reporting

Looking at this line

RCT_EXPORT_METHOD(enableCrashReporting:(NSArray*)arguments)

the native bridge expects an array to be passed when enabling crash reporting. The call in Countly.js does not match this signature:

CountlyReactNative.enableCrashReporting();

So either the call or the function signature should be adjusted for it to work.

Problems found when sending push notification from firebase.

Hello,

Can't send .js files directly from here. I uploaded our implementation (there may be another files too but we get them directly from Countly RN SDK documentation so there won't be any difference probably) to wetransfer.

Link: https://we.tl/t-zPDcYZ1S2O

Our problem:
We sent notification over firebase console, not from Countly dashboard and we are getting this error. I added image to find source of it.

In Summary:
Firebase -> Send Notification (no deeplink) -> Opens App (iOS) -> Crash (on some devices not on all of them)

Also I added crash report for detecting the error source quickly.

Regards,
Mithat.

FCM support

Currently we have GCM support and next version should have FCM support as well.

Variables are in global scope instead of wrapped in a scoped class, use JS ECMA6 standards

There are several variables in global scope, that could all be scoped within a class.
Suggest following https://standardjs.com/
Since this is a react-native SDK, this could be built to follow ECMAScript 6 patterns. Constants can be used as const, a class can provide scope, local variables can be class properties, etc.

Suggest a default export such as export default class Countly {...}

Here is a rough outline (note, this has not been tested, shown here only for reference and to provide a potential approach and discussion points)

import { Platform, NativeModules, AsyncStorage, Dimensions, AppState } from 'react-native';
import DeviceInfo from 'react-native-device-info'

// semi-colons not required
const SESSION_INTERVAL = 60
const sdkVersion = "1.0.6"
const sdkName = "countly-sdk-react-native"

export default class Countly {
  constructor() {
    this.isDebug = false
    this.isInit = false
    this.isManualSessionHandling = false
    this.isReady = false
    this.startTime = new Date().getTime()
    this.storedEvents = {}
    this.queue = []
    // etc, more local class variables here
  }

  // Ajax global var not needed, could be as follows within this class,
  // or common functions like this could be pulled into a separate util wrapper
  getTime() {
    return new Date().getTime()
  }

  // instead of Ajax.id, use a class method, and create a uuid, also has less chance of collision
  // see the countly web sdk:  https://github.com/Countly/countly-sdk-web/blob/2f7e4ffbd5b17a7422a7a9bcfb2830d299f69572/lib/countly.js#L1282
  // you can call this from within this class using 
  // var example = this.generatedUUID()

  generateUUID () {
    var d = new Date().getTime()
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = (d + Math.random() * 16) % 16 | 0
        d = Math.floor(d / 16)
        return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
    })
  }

  // example of public Countly SDK methods as static functions
  // Countly.startEvent
  static startEvent (events) {
    events.dur = this.getTime()
     // I don't think storedEvents needs to be in global scope, use class scoped prop
    this.storedEvents[events.key] = events
  }

  // Countly.recordEvent
  static recordEvent(event) {
     // do work here
  }

  static someUtilityFunction(foo) {
    // Static method calls are made directly on the class and are not callable on instances of the class. 
  }


}

if you don't like calling this.localFunction for utils, and want to separate utility functions or web service calls (fetch wrappers) into another file, to keep them separate from the main countly SDK methods, one option would be pull it out them out a separate file and make the functions (or methods if class) available via another in another import (but that may be overkill)

// example of a separate CountlyUtil.js file
// Countly.js would need to import this to use the functions

function  getTime() {
    return new Date().getTime()
  }

function someOtherThing() {
   return 123
}

export {
   getTime,
   someOtherThing
}

Or this could be another class with several static functions, there are a few ways to approach breaking the code into functional areas (again may be overkill)

Is it possible to support Expo?

Countly is really cool.

I tried using Docker and it look awesome.

Do you have any plan to create a version which support Expo, or should I create by my self?

Thank you for great service!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.