Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TIMOB-26294] TiAPI: Notify app about user-interactions #10248

Merged
merged 17 commits into from
Sep 26, 2018
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1497,9 +1497,7 @@ public void onUserInteraction()
{
Log.d(TAG, "Activity " + this + " onUserInteraction", Log.DEBUG_MODE);

if (activityProxy != null) {
activityProxy.fireEvent(TiC.EVENT_USER_INTERACTION, null);
}
TiApplication.getInstance().fireAppEvent(TiC.EVENT_USER_INTERACTION, null);

super.onUserInteraction();
}
Expand Down
20 changes: 0 additions & 20 deletions apidoc/Titanium/Android/Activity.yml
Original file line number Diff line number Diff line change
Expand Up @@ -344,26 +344,6 @@ events:
in the Android Developer Reference.
since: "3.2.0"

- name: userinteraction
summary: Called whenever a key, touch, or trackball event is dispatched to the activity.
description: |
Implement this method if you wish to know that the user has interacted with the device in some
way while your activity is running. This event and `userleavehint` are intended to help activities
manage status bar notifications intelligently; specifically, for helping activities determine the
proper time to cancel a notfication.

All calls to your activity's "userleavehint" event will be accompanied by calls to "userinteraction".
This ensures that your activity will be told of relevant user activity such as pulling down the
notification pane and touching an item there.

Note that this callback will be invoked for the touch down action that begins a touch gesture,
but may not be invoked for the touch-moved and touch-up actions that follow.

See also:
[onUserInteraction](https://developer.android.com/reference/android/app/Activity.html#onUserInteraction())
in the Android Developer Reference.
since: "7.4.0"

properties:

- name: actionBar
Expand Down
16 changes: 16 additions & 0 deletions apidoc/Titanium/App/App.yml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,22 @@ events:
platforms: [iphone, ipad]
since: '3.1.0'

- name: userinteraction
summary: Called whenever a key, touch, or trackball event is dispatched to the activity.
description: |
Implement this method if you wish to know that the user has interacted with the device in some
way while your app is running.

Note that this callback will be invoked for the touch down action that begins a touch gesture,
but may not be invoked for the touch-moved and touch-up actions that follow.

See also:
[onUserInteraction](https://developer.android.com/reference/android/app/Activity.html#onUserInteraction()) for Android.

On iOS, this event will be triggered each time a UITouchPhaseBegan event is handled by the UIApplication. For more information, see [sendEvent](https://developer.apple.com/documentation/uikit/uiapplication/1623043-sendevent).
platforms: [android, iphone, ipad]
since: "7.4.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be updated to 7.5.0 before merge now...


methods:
- name: fireSystemEvent
summary: Fire a system-level event such as <Titanium.App.EVENT_ACCESSIBILITY_ANNOUNCEMENT>.
Expand Down
11 changes: 11 additions & 0 deletions iphone/Classes/AppModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ - (void)_configure
selector:@selector(accessibilityVoiceOverStatusChanged:)
name:UIAccessibilityVoiceOverStatusChanged
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleUserInteraction:)
name:@"kTiUserInteraction"
object:nil];
}

- (NSString *)apiName
Expand Down Expand Up @@ -278,6 +282,13 @@ - (NSNumber *)disableNetworkActivityIndicator
return NUMBOOL([TiApp app].disableNetworkActivityIndicator);
}

- (void)handleUserInteraction:(id)notification
{
if ([self _hasListeners:@"userinteraction"]) {
[self fireEvent:@"userinteraction" withObject:nil];
}
}

//To fire the keyboard frame change event.
- (void)keyboardFrameChanged:(NSNotification *)notification
{
Expand Down
6 changes: 6 additions & 0 deletions iphone/Classes/TiUIApplication.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#import <UIKit/UIKit.h>

@interface TiUIApplication : UIApplication {
}
- (void)sendEvent:(UIEvent *)event;
@end
16 changes: 16 additions & 0 deletions iphone/Classes/TiUIApplication.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#import "TiUIApplication.h"

@implementation TiUIApplication

- (void)sendEvent:(UIEvent *)event
{
[super sendEvent:event];

for (UITouch *touch in event.allTouches) {
if (touch.phase == UITouchPhaseBegan) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"kTiUserInteraction" object:nil];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am starting to become unsure if we should really have this in the core. I understand the purpose for you, but this was requested by maybe 5 devs over the last years, and it must have some kind of performance hit if we post an internal notification for every tap that is made in an app.

Copy link
Contributor Author

@JorenVos JorenVos Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree with your concerns about potential perfomance hit. On Android, the onUserInteraction will also loop over the event listeners in order to fire an event. It can have performance impact on both platforms, but while testing it, I wasn't able to "feel"/measure it.

I also understand that on Android, we're firing an event for a native event (onUserInteraction). iOS doesn't have this event by default, so this workaround is mentioned as a solution for this problem (https://blog.gaelfoppolo.com/detecting-user-inactivity-in-ios-application-684b0eeeef5b)

In order to improve performance, there should be an if somewhere in order to only post internal notifications when there are listeners registered, but I wasn't able to find a way on how to implement this. This feature might be requested by 'only 5 devs', but I think this can't be fixed by using a module, as you need to extend the UIApplication class and register it in the main.m file of your project.

In a use case from our customer, we're in the need of implementing a way to automatically logout after x-seconds of non-activity. The way it's implemented now (firing events for user interctions) is the only way to catch user activity in Titanium, so we can handle further stuff in our Javascript code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use a design that has a property (let's say trackUserInteraction) together with the userinteraction event, we could wrap the special code out using preprocessor macros on iOS. For Android, we could maybe add the handler only if the property is set or at least use it to skip the event from firing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comment, but I don't have any knowledge about preprocessor macros.

On Android, I think that the event is only fired when there is a listener registered.

}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also lint here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont!


@end
6 changes: 6 additions & 0 deletions iphone/iphone/Titanium.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@
502A68E616EEAA7500661EF6 /* TiUIListViewProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 502A68D916EEAA7500661EF6 /* TiUIListViewProxy.m */; };
502A68EB16F0428500661EF6 /* TiViewTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 502A68EA16F0428500661EF6 /* TiViewTemplate.m */; };
5081CEF815F8100E00C881D8 /* TiExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 5081CEF715F8100E00C881D8 /* TiExceptionHandler.m */; };
673144D6211DBAD7001BDBF2 /* TiUIApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 673144D5211DBAD7001BDBF2 /* TiUIApplication.m */; };
823CC8AC1B7F0E4D00D220C7 /* WatchSessionModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 823CC8AB1B7F0E4D00D220C7 /* WatchSessionModule.m */; };
838159E21B7A9632002EE811 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 838159EC1B7C3EFA002EE811 /* Assets.xcassets */; };
838267951D9DAD6800F99248 /* TiLogServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 838267941D9DAD6800F99248 /* TiLogServer.m */; };
Expand Down Expand Up @@ -776,6 +777,8 @@
502A68EA16F0428500661EF6 /* TiViewTemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiViewTemplate.m; sourceTree = "<group>"; };
5081CEF615F8100E00C881D8 /* TiExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiExceptionHandler.h; sourceTree = "<group>"; };
5081CEF715F8100E00C881D8 /* TiExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiExceptionHandler.m; sourceTree = "<group>"; };
673144D4211DBAD7001BDBF2 /* TiUIApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TiUIApplication.h; path = ../Classes/TiUIApplication.h; sourceTree = "<group>"; };
673144D5211DBAD7001BDBF2 /* TiUIApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TiUIApplication.m; path = ../Classes/TiUIApplication.m; sourceTree = "<group>"; };
823CC8AA1B7F0E4D00D220C7 /* WatchSessionModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WatchSessionModule.h; sourceTree = "<group>"; };
823CC8AB1B7F0E4D00D220C7 /* WatchSessionModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WatchSessionModule.m; sourceTree = "<group>"; };
838159EC1B7C3EFA002EE811 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2002,6 +2005,8 @@
29B97315FDCFA39411CA2CEA /* Other Sources */ = {
isa = PBXGroup;
children = (
673144D4211DBAD7001BDBF2 /* TiUIApplication.h */,
673144D5211DBAD7001BDBF2 /* TiUIApplication.m */,
32CA4F630368D1EE00C91783 /* Titanium_Prefix.pch */,
29B97316FDCFA39411CA2CEA /* main.m */,
241EAA21118AB3BB0081A5BE /* defines.h */,
Expand Down Expand Up @@ -2587,6 +2592,7 @@
159C599B1C383645009A8860 /* TiUIiOSTableViewCellSelectionStyleProxy.m in Sources */,
24CA8B95111161FE0084E2DE /* TiUIProgressBarProxy.m in Sources */,
24CA8B96111161FE0084E2DE /* TiUIProgressBar.m in Sources */,
673144D6211DBAD7001BDBF2 /* TiUIApplication.m in Sources */,
24CA8B97111161FE0084E2DE /* TiUIOptionDialogProxy.m in Sources */,
24CA8B98111161FE0084E2DE /* TiUINavBarButton.m in Sources */,
24CA8B99111161FE0084E2DE /* TiUILabelProxy.m in Sources */,
Expand Down
33 changes: 17 additions & 16 deletions iphone/iphone/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,25 @@
//automatically replaced and built on the fly - when running in
//XCode give some reasonable values

NSString * const TI_APPLICATION_DEPLOYTYPE = @"development";
NSString * const TI_APPLICATION_ID = @"com.appcelerator.kitchensink.xcode";
NSString * const TI_APPLICATION_PUBLISHER = @"Appcelerator";
NSString * const TI_APPLICATION_URL = @"http://www.appcelerator.com";
NSString * const TI_APPLICATION_NAME = @"Kitchen Sink (XCode)";
NSString * const TI_APPLICATION_VERSION = @"1.0";
NSString * const TI_APPLICATION_DESCRIPTION = @"Kitchen Sink from XCode";
NSString * const TI_APPLICATION_COPYRIGHT = @"Appcelerator";
NSString * const TI_APPLICATION_GUID = @"25FE4B6E-7DA9-4344-B55B-25195570860F";
NSString *const TI_APPLICATION_DEPLOYTYPE = @"development";
NSString *const TI_APPLICATION_ID = @"com.appcelerator.kitchensink.xcode";
NSString *const TI_APPLICATION_PUBLISHER = @"Appcelerator";
NSString *const TI_APPLICATION_URL = @"http://www.appcelerator.com";
NSString *const TI_APPLICATION_NAME = @"Kitchen Sink (XCode)";
NSString *const TI_APPLICATION_VERSION = @"1.0";
NSString *const TI_APPLICATION_DESCRIPTION = @"Kitchen Sink from XCode";
NSString *const TI_APPLICATION_COPYRIGHT = @"Appcelerator";
NSString *const TI_APPLICATION_GUID = @"25FE4B6E-7DA9-4344-B55B-25195570860F";
BOOL const TI_APPLICATION_ANALYTICS = YES;
BOOL const TI_APPLICATION_SHOW_ERROR_CONTROLLER = YES;
NSString * const TI_APPLICATION_RESOURCE_DIR = nil;
NSString * const TI_APPLICATION_BUILD_TYPE = nil;
NSString *const TI_APPLICATION_RESOURCE_DIR = nil;
NSString *const TI_APPLICATION_BUILD_TYPE = nil;

int main(int argc, char *argv[]) {
int main(int argc, char *argv[])
{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, @"TiApp");
[pool release];
return retVal;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, @"TiUIApplication", @"TiApp");
[pool release];
return retVal;
}
31 changes: 15 additions & 16 deletions support/iphone/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,26 @@
#define _QUOTEME(x) #x
#define STRING(x) _QUOTEME(x)

NSString * const TI_APPLICATION_DEPLOYTYPE = @"__DEPLOYTYPE__";
NSString * const TI_APPLICATION_ID = @"__APP_ID__";
NSString * const TI_APPLICATION_PUBLISHER = @"__APP_PUBLISHER__";
NSString * const TI_APPLICATION_URL = @"__APP_URL__";
NSString * const TI_APPLICATION_NAME = @"__APP_NAME__";
NSString * const TI_APPLICATION_VERSION = @"__APP_VERSION__";
NSString * const TI_APPLICATION_DESCRIPTION = @"__APP_DESCRIPTION__";
NSString * const TI_APPLICATION_COPYRIGHT = @"__APP_COPYRIGHT__";
NSString * const TI_APPLICATION_GUID = @"__APP_GUID__";
NSString *const TI_APPLICATION_DEPLOYTYPE = @"__DEPLOYTYPE__";
NSString *const TI_APPLICATION_ID = @"__APP_ID__";
NSString *const TI_APPLICATION_PUBLISHER = @"__APP_PUBLISHER__";
NSString *const TI_APPLICATION_URL = @"__APP_URL__";
NSString *const TI_APPLICATION_NAME = @"__APP_NAME__";
NSString *const TI_APPLICATION_VERSION = @"__APP_VERSION__";
NSString *const TI_APPLICATION_DESCRIPTION = @"__APP_DESCRIPTION__";
NSString *const TI_APPLICATION_COPYRIGHT = @"__APP_COPYRIGHT__";
NSString *const TI_APPLICATION_GUID = @"__APP_GUID__";
BOOL const TI_APPLICATION_ANALYTICS = __APP_ANALYTICS__;
BOOL const TI_APPLICATION_SHOW_ERROR_CONTROLLER = __SHOW_ERROR_CONTROLLER__;
NSString * const TI_APPLICATION_BUILD_TYPE = @"__APP_DEPLOY_TYPE__";
NSString *const TI_APPLICATION_BUILD_TYPE = @"__APP_DEPLOY_TYPE__";

#ifdef TARGET_IPHONE_SIMULATOR
NSString * const TI_APPLICATION_RESOURCE_DIR = @"__APP_RESOURCE_DIR__";
NSString *const TI_APPLICATION_RESOURCE_DIR = @"__APP_RESOURCE_DIR__";
#endif

int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

int retVal = UIApplicationMain(argc, argv, nil, @"TiApp");
[pool release];
return retVal;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, @"TiUIApplication", @"TiApp");
[pool release];
return retVal;
}