Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-25618] App is unable to access Localytics method properly

GitHub Issuen/a
TypeBug
PriorityCritical
StatusClosed
ResolutionFixed
Resolution Date2018-05-15T20:42:13.000+0000
Affected Version/sn/a
Fix Version/sn/a
ComponentsiOS
LabelsEscalation
ReporterVictor Vazquez Montero
AssigneeHans Knöchel
Created2017-12-19T20:50:08.000+0000
Updated2018-05-15T20:43:05.000+0000

Description

Description:

Customer is having issues accessing Localytics method properly

Code:

We are using the Localytics SDK for Analytics and we are having issues accessing a specific method. Attached is the pod file that we are using. We are using the setOptions method to set the "max_monitoring_regions" option in our titanium app but it does not work. Below is the code snippet. Can you check if we are using the method in the right way with the right arguments? Code:
var TiApp = require('Titanium/TiApp'); 

var Localytics = require("Localytics/Localytics"); 
console.log("launction options are " + Localytics + localyticsKey); 
Localytics.autoIntegrateLaunchOptions(³APP_KEY", TiApp.app.launchOptions);
Localytics.setLoggingEnabled(true); 
var options = { "max_monitoring_regions" : 2 };
Localytics.setOptions(options); 

Podfile:

{quote}install! 'cocoapods', :integrate_targets => false platform :ios, '7.0' target 'myWorkplace' do pod 'LocalyticsStaticFramework', '~> 4.2' end {quote}

Request:

Can you see any issues in their implementation or have any changes been made in hyperloop that they need to address in the implementation?

Attachments

FileDateSize
beaconcrash.txt2018-02-21T23:09:33.000+00001025317
com.abc.localytics-iphone-1.0.0.zip2018-04-29T07:13:46.000+00007069307
index.js2018-01-25T20:45:08.000+000049214
iOSBeacon.js2018-01-25T20:45:07.000+00005806
iOSBeaconCrashLog.txt2018-01-25T20:45:09.000+00007522403
localytics_module_error_log.txt2018-04-27T19:38:40.000+00001005765
Localytics.h2017-12-20T20:58:25.000+000052437
LogOutput.txt2018-02-13T23:43:25.000+0000686275
WorkplaceSvc_Dev__2-5-18_12-44_PM.crash2018-02-05T17:56:13.000+000055509
WorkplaceSvc_Dev.app.dSYM.zip2018-02-21T23:09:38.000+00006673163
WorkplaceSvc_Dev 2-13-18, 5-17 PM.crash2018-02-13T23:43:24.000+000062211
WorkplaceSvc_Dev 2-21-18, 4-49 PM.crash2018-02-21T23:09:33.000+000083731

Comments

  1. Ajith Rohini 2017-12-20

    [[~emerriman], Can you please take a look at this. Its a pressing issue for ABC.
  2. Srinivasan Pulipakkam 2017-12-20

    cc [~pkalita] [~arohini] I don't know if the localytics sdk is supported by us or not. Is there any other information as to what is not working ? The ticket just mentions a code snippet but it is not clear what behavior they are seeing and why they are saying it is not working ?
  3. Victor Vazquez Montero 2017-12-20

    [~spulipakkam] they are doubtful the that method names passed through hyperloop are being implemented correctly. Is there any way to map out for them what the Method names would be?
  4. Srinivasan Pulipakkam 2017-12-20

    [^Localytics.h] [~emerriman] I am not sure if we do something like this (see comment from Victor above). I have attached the Localytics method signatures i got from their sdk. [~vvazquezmontero] I still feel the ticket needs more info. Have they used localytics sdk with hyperloop before ? Are they moving to a new localytics sdk version ( 3 to 4) . What kind of error are they seeing ? If we have not done this kind of mapping for any other native library i don't understand why we would need to do it for localytics?
  5. Victor Vazquez Montero 2017-12-20

    [~spulipakkam]I will ask those questions to the customer but according to them we have done this for them before and it is expected from us.
  6. Srinivasan Pulipakkam 2017-12-20

    [~vvazquezmontero] If we have done that for them before wouldn't it be for a subset or specific method signatures. Localytics is not a small sdk it is a lot of methods! If [~emerriman] confirms that this is something we would be able to do then i think we should ask the customer to give us a list of methods they would be using. I don't think we should be spending time on documenting the entire localytics sdk. They(localytic) themselves have not documented their APIs well.
  7. Jan Vennemann 2017-12-21

    [~vvazquezmontero], [~spulipakkam] the methods names are definitely correct, otherwise Hyperloop would throw an error at runtime that there is no such method. A quick debugging shows that the methods indeed reach the native side, but for some reason they don't show the expected behavior. Localytics.setLoggingEnabled(true) for example should enable the logging, but no log messages from Localytics are seen after making this call. Further investigating this right now.
  8. patilamrut 2017-12-21

    @Victor Vazquez Montero, @Srinivasan Pulipakkam , @Jan Vennemann , @Pooja Kalita we have been using localytics for long time now. Till now we have used init method, tagscreen, tagevent, set profile these methods are working fine for now. we have always used localytics static framework 4.2. I hope this helps.
  9. Jan Vennemann 2018-01-04

    [~morahman], [~emerriman]. did some more debugging and i couldn't find a reason why it does not work for the customer with this specific method yet. I tried several other methods and all of them seem to work as expected. As [~patilamrut] mentioned, they are also using Localytics successfully. The logging issues i mentioned in my previous comment are likely related to the way we retrieve logs. I verified with Localytics.isLoggingEnabled that the logging is actually enabled after calling Localytics.setLoggingEnabled(true), they just don't show up. I'll ping [~cbarber] on this to see if the he has any idea why this is happening. I even created a native module to verify that it's not in any way related to Hyperloop since it shows the same behavior. While we further validate the logging issues, is it possible to get more details from the customer about the exact issue? Localytics.setOptions is not documented anywhere except for one [Help Article](https://help.localytics.com/t/how-can-i-use-localytics-side-by-side-with-another-geofencing-or-beacon-service/400). Is there an easy way for us to verify the iOS monitoring limitations?
  10. patilamrut 2018-01-08

    We have created a native iOS project with localytics SDK and Estimote beacon SDK. With that we are able to use localytics setoptions method and use estimote sdk to monitor beacon. This proves that issue is clearly with hyperloop. As if i use hyperloop i cannot use setoptions method.
  11. Victor Vazquez Montero 2018-01-19

    Hello [~jvennemann] Amerisource has come back with a query: {quote}Based on our testing, the "Localytics.integrate("API_KEY")" does not send the analytics data to Localytics. We have not received any analytics data since the update we made yesterday. We are trying couple other methods that supplement the "Loclaytics.integrate()" method as mentioned in the Localytics documentation and testing it. I will keep updating our progress in this ticket. Please let us know if you have any insight in this matter. We request you to close this case after we confirm.{quote}
  12. Jan Vennemann 2018-01-23

    [~vvazquezmontero], after further investigation of this issue we think this not related to Hyperloop but rather an incompatibility of the used beacon module and Localytics auto integration. To test it they can use the following code, which replaces their iosBeaconLocator with a complete Hyperloop implementation:
        var NSUUID = require('Foundation/NSUUID');
        var CLBeacon = require('CoreLocation/CLBeacon');
        var CLBeaconRegion = require('CoreLocation/CLBeaconRegion');
        var CLLocationManager = require('CoreLocation/CLLocationManager');
        var { CLProximityUnknown, CLProximityImmediate, CLProximityNear, CLProximityFar, CLRegionStateInside } = require('CoreLocation');
        var ESTIMOTE_UUID = 'B9407F30-F5F8-466E-AFF9-25556B57FE6D';
        var handleProximity = null;
        var IDENTIFIER = 'Estimote Beacons';
        var locationManager = null;
        var beaconProximities = {};
        
        exports.startMonitoring = function(userProximityHandler) {
        	console.log("in starMonitoring for iOSBeacons");
        
        	handleProximity = userProximityHandler;
        
        	var LocationManagerDelegate = Hyperloop.defineClass('LocationManagerDelegate', 'NSObject', 'CLLocationManagerDelegate');
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:didEnterRegion:',
        		arguments: [ 'CLLocationManager', 'CLBeaconRegion' ],
        		callback: function didEnterRegion(locationManager, beaconRegion) {
        			Ti.API.debug('Entered beacon region ' + beaconRegion.identifier);
        			locationManager.startRangingBeaconsInRegion(beaconRegion);
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:didExitRegion:',
        		arguments: [ 'CLLocationManager', 'CLBeaconRegion' ],
        		callback: function didExitRegion(locationManager, beaconRegion) {
        			Ti.API.debug('Exited beacon region ' + beaconRegion.identifier);
        			locationManager.stopRangingBeaconsInRegion(beaconRegion);
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:didStartMonitoringForRegion:',
        		arguments: [ 'CLLocationManager', 'CLBeaconRegion' ],
        		callback: function didExitRegion(locationManager, beaconRegion) {
        			Ti.API.debug('Started monitoring beacon region ' + beaconRegion.identifier);
        			locationManager.requestStateForRegion(beaconRegion);
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:didDetermineState:forRegion:',
        		arguments: [ 'CLLocationManager', 'CLRegionState', 'CLBeaconRegion' ],
        		callback: function didExitRegion(locationManager, regionState, beaconRegion) {
        			if (regionState == CLRegionStateInside) {
        				Ti.API.debug('Already inside region ' + beaconRegion.identifier + ', start ranging.');
        				locationManager.startRangingBeaconsInRegion(beaconRegion);
        			}
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:monitoringDidFailForRegion:withError:',
        		arguments: [ 'CLLocationManager', 'CLBeaconRegion', 'NSError' ],
        		callback: function monitoringDidFailForRegion(locationManager, beaconRegion, error) {
        			Ti.API.error('Monitoring beacon region ' + beaconRegion.identifier + ' failed!');
        			Ti.API.error(error.localizedDescription);
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:didRangeBeacons:inRegion:',
        		arguments: [ 'CLLocationManager', 'NSArray', 'CLBeaconRegion'],
        		callback: function didRangeBeacons(locationManager, beacons, beaconRegion) {
        			Ti.API.debug(beacons.count + ' beacons in range');
        			for (var i = 0; i < beacons.count; i++) {
        				var beacon = CLBeacon.cast(beacons.objectAtIndex(i));
        				Ti.API.debug('Beacon ' + beacon.proximityUUID + ' proximity: ' + beacon.proximity);
        			}
        
        			reportCrossingsInRegion(beacons, beaconRegion, handleProximity);
        		}
        	});
        	LocationManagerDelegate.addMethod({
        		selector: 'locationManager:rangingBeaconsDidFailForRegion:withError:',
        		arguments: [ 'CLLocationManager', 'CLBeaconRegion', 'NSError' ],
        		callback: function rangingBeaconsDidFailForRegion(locationManager, beaconRegion, error) {
        			Ti.API.error('Ranging beacon region ' + beaconRegion.identifier + ' failed!');
        			Ti.API.error(error.localizedDescription);
        		}
        	});
        
        	locationManager = CLLocationManager.alloc().init();
        	locationManager.delegate = new LocationManagerDelegate();
        
        	var beaconRegion = CLBeaconRegion
        		.alloc()
        		.initWithProximityUUIDIdentifier(NSUUID.alloc().initWithUUIDString(ESTIMOTE_UUID), IDENTIFIER);
        	locationManager.startRangingBeaconsInRegion(beaconRegion);
        };
        
        exports.stopMonitoring = function(){
        	var rangedRegions = locationManager.rangedRegions;
        	for (var i = 0; i < rangedRegions.count; i++) {
        		locationManager.stopRangingBeaconsInRegion(rangedRegions[i]);
        	}
        };
        
        /**
         * @see https://github.com/jbeuckm/TiBeacons/blob/master/Classes/OrgBeuckmanTibeaconsModule.m#L398
         */
        function reportCrossingsInRegion(beacons, beaconRegion, callback) {
        	for (var i = 0; i < beacons.count; i++) {
        		var current = CLBeacon.cast(beacons.objectAtIndex(i));
        		var identifier = current.proximityUUID.UUIDString + '/' + current.major + '/' + current.minor;
        
        		var previous = beaconProximities[identifier];
        		if (previous && previous.proximity != current.proximity) {
        			var event = generateBeaconDetails(current);
        			event.identifier = beaconRegion.identifier,
        			event.fromProximity = stringifyProxymity(previous.proximity);
        			callback(event);
        		} else {
        			var event = generateBeaconDetails(current);
        			event.identifier = beaconRegion.identifier,
        			callback(event);
        		}
        
        		beaconProximities[identifier] = current;
        	}
        }
        
        /**
         * @see https://github.com/jbeuckm/TiBeacons/blob/master/Classes/OrgBeuckmanTibeaconsModule.m#L450
         */
        function generateBeaconDetails(beacon) {
        	return {
        		uuid: beacon.proximityUUID.UUIDString,
        		major: beacon.major,
        		minor: beacon.minor,
        		proximity: stringifyProxymity(beacon.proximity),
        		accuracy: beacon.accuracy,
        		rssi: beacon.rssi
        	};
        }
        
        /**
         * @see https://github.com/jbeuckm/TiBeacons/blob/master/Classes/OrgBeuckmanTibeaconsModule.m#L498
         */
        function stringifyProxymity(beaconProximity) {
        	switch (beaconProximity) {
        		case CLProximityNear:
        			return 'near';
        		case CLProximityImmediate:
        			return 'immediate';
        		case CLProximityFar:
        			return 'far';
        		case CLProximityUnknown:
        		default:
        			return 'unknown';
        		}
        }
        
    This will work with Localytics.autoIntegrateLaunchOptions and includes all delegate methods required for monitoring and ranging beacons. Another minor note: They only use the When-In-Use Authorization style where monitoring regions is not allowed. However, for the sake of completeness, the above code snippet also has monitoring delegates setup. This also means that Localytics.setOptions() is not necessary since Localytics cannot monitor regions and their code only uses ranging.
  13. Victor Vazquez Montero 2018-01-24

    Hey Jan, I've shared that with the customer and will update you once then confirm
  14. Victor Vazquez Montero 2018-01-25

    [~jvennemann] they are now facing crashes while using the app: {quote}Hello Team, Thanks for providing the Hyperloop beacon source code for iOS. We implemented the source code in the project and the beacon monitoring started to work. Although, the iOS app was crashing with a SIGSEGV error after opening the app and staying in it for sometime (less than 2 min of navigating in the app). Attached are the crash details and the files that we changed. Also, per Jan's suggestion, I also added the "AlwaysUse" authorization for location.
    <key>NSLocationAlwaysUsageDescription</key> 
        <string>This application monitors your location to show you information of places/events you're passing by.</string><key>NSCameraUsageDescription</key> 
    Steps to replicate the crash: - Use the below code and run the app - The app requests user for location permission - On granting permission, the app monitors beacons and displays the beacon information if it finds one - Navigate to the app by selecting the location (Valley forge) - Tap on 'View Schedule' - After you go through few screens, the app crashes. There is no specific screen/point/flow where the app crashes. On observing the crash logs, it seems to be a SIGSEGV error. Please let us know if we are missing anything.{quote} Files: [^index.js] [^iOSBeacon.js] [^iOSBeaconCrashLog.txt]
  15. Mostafizur Rahman 2018-01-30

    [~jvennemann] Is there any update here? The customer is asking for updates.
  16. Jan Vennemann 2018-01-30

    Looking into it right now! I'll keep you posted once i know more.
  17. Jan Vennemann 2018-01-30

    [~vvazquezmontero], [~mrahman], a couple of questions as i'm not able to reproduce the crash in my environment. - Did the crash only occur after changes to the code in index.js? - There is a minor bug in my initial beacon locator implementation which results in the beacon proximity always being "unknown". I was too optimistic and thought destructuring would work. To fix it they have to replace line 5 in iosBeaconLocator.js with
        var CoreLocation = require('CoreLocation');
        var CLProximityNear = CoreLocation.CLProximityNear;
        var CLProximityImmediate = CoreLocation.CLProximityImmediate;
        var CLProximityFar = CoreLocation.CLProximityFar;
        var CLProximityUnknown = CoreLocation.CLProximityUnknown;
        
    - Can they provide a full crash report as a .crash file? The plain device log makes it hard to exactly identify where it crashed in JavaScriptCore.
  18. Victor Vazquez Montero 2018-02-01

    [~jvennemann] Can you provide me what you see on your end and the app version and the environment (QA/Dev) that you’re pointing you? Request from customer
  19. Victor Vazquez Montero 2018-02-05

    [~jvennemann] They were able to resolve the issues they were seeing on friday through a call but now they are seeing a crash and have shared the crash report: [^WorkplaceSvc_Dev__2-5-18_12-44_PM.crash]
  20. Jan Vennemann 2018-02-06

    Thanks [~vvazquezmontero], that helps a lot! Looking into it now.
  21. Victor Vazquez Montero 2018-02-08

    [~jvennemann] do we have anything to share with the customer?
  22. Victor Vazquez Montero 2018-02-21

    Hello [~jvennemann] they have provided the logs needed and also commented: Also, just an FYI - we are targeting the app to use the latest 7.0.2 SDK. Just want to ensure that the latest hyperloop has the updates needed for this issue. [^beaconcrash.txt] [^WorkplaceSvc_Dev 2-21-18, 4-49 PM.crash] [^WorkplaceSvc_Dev.app.dSYM.zip] let me know if you need anything else.
  23. Ajith Rohini 2018-03-13

    [~amukherjee] Can we pls make this a priority?
  24. Abir Mukherjee 2018-03-13

    [~arohini] The issue we have is that Jan is our only developer who has the the knowledge deep enough to fix it. Hans proposed a workaround, and I'll work with him tomorrow to test it. But for an actual fix, it won't be until next week at the earliest when Jan gets back
  25. Hans Knöchel 2018-05-05

    I have updated the official Localytics module based on the changes [~gmathews] made before by: - updating the Localytics SDK to 5.1.0 (latest) - adding startMonitoring(callback) and stopMonitoring() to the module API This allows you to use beacon monitoring without additional modules. It's nearly 1:1 the Hyperloop implementation in native code. I have also made a pull request against the official Localytics repository and it contains the new module binary (com.localytics-iphone-5.1.0.zip): https://github.com/localytics/localytics-titanium/pull/6 P.S.: Checking out the PR locally will also fix the error seen before ("invalid bitcode signature") that I addressed. *EDIT*: I have made a test app that is successfully able to range beacons:
        [INFO]  test_localytics/1.0 (6.2.2.42c7196)
        [INFO]  Starting monitoring ...
        [INFO]  No location permissions, yet. Requesting ...
        [INFO]  Permissions new granted, let's go!
        [INFO]  {
        [INFO]      accuracy = "0.215443";
        [INFO]      identifier = "Estimote Beacons";
        [INFO]      major = 2;
        [INFO]      minor = 1000;
        [INFO]      proximity = immediate;
        [INFO]      rssi = "-46";
        [INFO]      uuid = "B9407F30-F5F8-466E-AFF9-25556B57FE6D";
        [INFO]  }
        [INFO]  {
        [INFO]      accuracy = "0.315342";
        [INFO]      fromProximity = immediate;
        [INFO]      identifier = "Estimote Beacons";
        [INFO]      major = 2;
        [INFO]      minor = 1000;
        [INFO]      proximity = near;
        [INFO]      rssi = "-52";
        [INFO]      uuid = "B9407F30-F5F8-466E-AFF9-25556B57FE6D";
        [INFO]  }
        
    It uses the above module and can be downloaded [here](https://www.dropbox.com/s/vfam1mxn0atnhbk/test_localytics.zip?dl=1). I assume this should resolve all remaining issues regarding beacons. If there is more hands on help needed, please let me know. Thanks!

JSON Source