-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jeroen van Dijk
committed
Oct 4, 2017
1 parent
e9b65ed
commit e8a6a63
Showing
22 changed files
with
2,006 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
TODO: place your license here and we'll include it in the module distribution |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# Titanium Location Permission | ||
This module gives you the possibility to shortcircuit the current iOS location permission from Titanium to properly support iOS 11 its new way of location permissions. | ||
|
||
## Follow Guide | ||
|
||
### Setup | ||
|
||
1. Integrate the module into the `modules` folder and define them into the `tiapp.xml` file: | ||
|
||
```xml | ||
<modules> | ||
<module platform="iphone" version="0.1.0">ti.locationpermission</module> | ||
</modules> | ||
``` | ||
|
||
### Usage | ||
1. Check if you have a location permission | ||
|
||
```js | ||
var locationPermission = (OS_IOS) ? require('ti.locationpermission') : Ti.Geolocation; | ||
|
||
if (locationPermission.hasLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE)) { | ||
alert('true'); | ||
} | ||
``` | ||
|
||
1. Request or upgrade location permission | ||
|
||
```js | ||
var locationPermission = (OS_IOS) ? require('ti.locationpermission') : Ti.Geolocation; | ||
|
||
locationPermission.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_WHEN_IN_USE, function(e) { | ||
alert(e.success); | ||
}); | ||
|
||
locationPermission.requestLocationPermissions(Ti.Geolocation.AUTHORIZATION_ALWAYS, function(e) { | ||
if (OS_IOS && e.authorizationStatus !== Ti.Geolocation.AUTHORIZATION_ALWAYS) { | ||
alert('Permission wasn\'t upgraded'); | ||
} | ||
}); | ||
``` | ||
|
||
Cheers! | ||
|
||
## Build yourself | ||
|
||
### iOS | ||
|
||
If you already have Titanium installed, skip the first 2 steps, if not let's install Titanium locally. | ||
|
||
1. `brew install yarn --without-node` to install yarn without relying on a specific Node version | ||
1. In the ios directory execute `yarn install` | ||
1. Alter the `titanium.xcconfig` to build with the preferred SDK | ||
1. To build the module execute `rm -rf build && ./node_modules/.bin/ti build -p ios --build-only` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Place your assets like PNG files in this directory and they will be packaged | ||
with your module. | ||
|
||
All JavaScript files in the assets directory are IGNORED except if you create a | ||
file named "ti.locationpermission.js" in this directory in which case it will be | ||
wrapped by native code, compiled, and used as your module. This allows you to | ||
run pure JavaScript modules that are pre-compiled. | ||
|
||
Note: Mobile Web does not support this assets directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# ti.locationpermission Module | ||
|
||
## Description | ||
|
||
TODO: Enter your module description here | ||
|
||
## Accessing the ti.locationpermission Module | ||
|
||
To access this module from JavaScript, you would do the following: | ||
|
||
var ti_locationpermission = require("ti.locationpermission"); | ||
|
||
The ti_locationpermission variable is a reference to the Module object. | ||
|
||
## Reference | ||
|
||
TODO: If your module has an API, you should document | ||
the reference here. | ||
|
||
### ti_locationpermission.function | ||
|
||
TODO: This is an example of a module function. | ||
|
||
### ti_locationpermission.property | ||
|
||
TODO: This is an example of a module property. | ||
|
||
## Usage | ||
|
||
TODO: Enter your usage example here | ||
|
||
## Author | ||
|
||
TODO: Enter your author name, email and other contact | ||
details you want to share here. | ||
|
||
## License | ||
|
||
TODO: Enter your license/legal information here. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// This is a test harness for your module | ||
// You should do something interesting in this harness | ||
// to test out the module and to provide instructions | ||
// to users on how to use it by example. | ||
|
||
|
||
// open a single window | ||
var win = Ti.UI.createWindow({ | ||
backgroundColor:'white' | ||
}); | ||
var label = Ti.UI.createLabel(); | ||
win.add(label); | ||
win.open(); | ||
|
||
// TODO: write your module tests here | ||
var ti_locationpermission = require('ti.locationpermission'); | ||
Ti.API.info("module is => " + ti_locationpermission); | ||
|
||
label.text = ti_locationpermission.example(); | ||
|
||
Ti.API.info("module exampleProp is => " + ti_locationpermission.exampleProp); | ||
ti_locationpermission.exampleProp = "This is a test value"; | ||
|
||
if (Ti.Platform.name == "android") { | ||
var proxy = ti_locationpermission.createExample({ | ||
message: "Creating an example Proxy", | ||
backgroundColor: "red", | ||
width: 100, | ||
height: 100, | ||
top: 100, | ||
left: 150 | ||
}); | ||
|
||
proxy.printMessage("Hello world!"); | ||
proxy.message = "Hi world!. It's me again."; | ||
proxy.printMessage("Hello world!"); | ||
win.add(proxy); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* ti.locationpermission | ||
* | ||
* Created by Your Name | ||
* Copyright (c) 2017 Your Company. All rights reserved. | ||
*/ | ||
|
||
#import "TiModule.h" | ||
#import <CoreLocation/CoreLocation.h> | ||
|
||
NSString *const kTiGeolocationUsageDescriptionWhenInUse = @"NSLocationWhenInUseUsageDescription"; | ||
NSString *const kTiGeolocationUsageDescriptionAlways = @"NSLocationAlwaysUsageDescription"; | ||
NSString *const kTiGeolocationUsageDescriptionAlwaysAndWhenInUse = @"NSLocationAlwaysAndWhenInUseUsageDescription"; | ||
|
||
@interface TiLocationpermissionModule : TiModule <CLLocationManagerDelegate> | ||
{ | ||
CLLocationManager *locationPermissionManager; | ||
CLAuthorizationStatus oldStatus; | ||
KrollCallback *authorizationCallback; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
/** | ||
* ti.locationpermission | ||
* | ||
* Created by Your Name | ||
* Copyright (c) 2017 Your Company. All rights reserved. | ||
*/ | ||
|
||
#import "TiLocationpermissionModule.h" | ||
#import "TiBase.h" | ||
#import "TiHost.h" | ||
#import "TiUtils.h" | ||
|
||
@implementation TiLocationpermissionModule | ||
|
||
#pragma mark Internal | ||
|
||
// this is generated for your module, please do not change it | ||
-(id)moduleGUID | ||
{ | ||
return @"1fc6c195-8d20-4733-af97-5d1755a9387a"; | ||
} | ||
|
||
// this is generated for your module, please do not change it | ||
-(NSString*)moduleId | ||
{ | ||
return @"ti.locationpermission"; | ||
} | ||
|
||
#pragma mark Lifecycle | ||
|
||
-(void)startup | ||
{ | ||
// this method is called when the module is first loaded | ||
// you *must* call the superclass | ||
[super startup]; | ||
|
||
NSLog(@"[INFO] %@ loaded",self); | ||
} | ||
|
||
-(void)shutdown:(id)sender | ||
{ | ||
// this method is called when the module is being unloaded | ||
// typically this is during shutdown. make sure you don't do too | ||
// much processing here or the app will be quit forceably | ||
|
||
// you *must* call the superclass | ||
[super shutdown:sender]; | ||
} | ||
|
||
- (CLLocationManager *)locationPermissionManager | ||
{ | ||
// if we don't have an instance, create it | ||
if (locationPermissionManager == nil) { | ||
locationPermissionManager = [[CLLocationManager alloc] init]; | ||
locationPermissionManager.delegate = self; | ||
} | ||
return locationPermissionManager; | ||
} | ||
|
||
#pragma mark Cleanup | ||
|
||
-(void)dealloc | ||
{ | ||
RELEASE_TO_NIL(locationPermissionManager); | ||
// release any resources that have been retained by the module | ||
[super dealloc]; | ||
} | ||
|
||
#pragma mark Internal Memory Management | ||
|
||
-(void)didReceiveMemoryWarning:(NSNotification*)notification | ||
{ | ||
// optionally release any resources that can be dynamically | ||
// reloaded once memory is available - such as caches | ||
[super didReceiveMemoryWarning:notification]; | ||
} | ||
|
||
- (void)executeAndReleaseCallbackWithCode:(NSInteger)code andMessage:(NSString *)message | ||
{ | ||
if (authorizationCallback == nil) { | ||
return; | ||
} | ||
|
||
NSMutableDictionary *propertiesDict = [TiUtils dictionaryWithCode:code message:message]; | ||
NSArray *invocationArray = [[NSArray alloc] initWithObjects:&propertiesDict count:1]; | ||
[authorizationCallback call:invocationArray thisObject:self]; | ||
|
||
[invocationArray release]; | ||
RELEASE_TO_NIL(message); | ||
RELEASE_TO_NIL(authorizationCallback); | ||
RELEASE_TO_NIL(locationPermissionManager); | ||
} | ||
|
||
#pragma Public APIs | ||
|
||
- (NSNumber *)hasLocationPermissions:(id)args | ||
{ | ||
BOOL locationServicesEnabled = [CLLocationManager locationServicesEnabled]; | ||
CLAuthorizationStatus currentPermissionLevel = [CLLocationManager authorizationStatus]; | ||
oldStatus = currentPermissionLevel; | ||
id value = [args objectAtIndex:0]; | ||
ENSURE_TYPE(value, NSNumber); | ||
CLAuthorizationStatus requestedPermissionLevel = [TiUtils intValue:value]; | ||
return NUMBOOL(locationServicesEnabled && currentPermissionLevel == requestedPermissionLevel); | ||
} | ||
|
||
- (void)requestLocationPermissions:(id)args | ||
{ | ||
id value = [args objectAtIndex:0]; | ||
ENSURE_TYPE(value, NSNumber); | ||
|
||
// Store the authorization callback for later usage | ||
if ([args count] == 2) { | ||
RELEASE_TO_NIL(authorizationCallback); | ||
ENSURE_TYPE([args objectAtIndex:1], KrollCallback); | ||
authorizationCallback = [[args objectAtIndex:1] retain]; | ||
} | ||
|
||
CLAuthorizationStatus requested = [TiUtils intValue:value]; | ||
CLAuthorizationStatus currentPermissionLevel = [CLLocationManager authorizationStatus]; | ||
oldStatus = currentPermissionLevel; | ||
|
||
if (currentPermissionLevel == kCLAuthorizationStatusAuthorizedWhenInUse && requested == kCLAuthorizationStatusAuthorizedWhenInUse) { | ||
[self executeAndReleaseCallbackWithCode:0 andMessage:nil]; | ||
return; | ||
} else if (currentPermissionLevel == kCLAuthorizationStatusAuthorizedAlways && requested == kCLAuthorizationStatusAuthorizedAlways) { | ||
[self executeAndReleaseCallbackWithCode:0 andMessage:nil]; | ||
return; | ||
} else if (currentPermissionLevel == kCLAuthorizationStatusDenied) { | ||
NSString *message = @"The user denied access to use location services."; | ||
[self executeAndReleaseCallbackWithCode:1 andMessage:message]; | ||
return; | ||
} | ||
|
||
NSString *errorMessage = nil; | ||
|
||
if (requested == kCLAuthorizationStatusAuthorizedWhenInUse) { | ||
NSLog(@"[DEBUG] %@", @"Requesting when in use authorize"); | ||
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:kTiGeolocationUsageDescriptionWhenInUse]) { | ||
if (currentPermissionLevel == kCLAuthorizationStatusAuthorizedAlways) { | ||
errorMessage = @"Cannot change already granted permission from AUTHORIZATION_ALWAYS to AUTHORIZATION_WHEN_IN_USE"; | ||
} else { | ||
NSLog(@"[DEBUG] %@", @"Requesting when in use authorize with key set"); | ||
TiThreadPerformOnMainThread(^{ | ||
[[self locationPermissionManager] requestWhenInUseAuthorization]; | ||
}, | ||
NO); | ||
} | ||
} else { | ||
errorMessage = [NSString stringWithFormat:@"The %@ key must be defined in your tiapp.xml in order to request this permission", kTiGeolocationUsageDescriptionWhenInUse]; | ||
} | ||
return; | ||
} | ||
if (requested == kCLAuthorizationStatusAuthorizedAlways) { | ||
NSLog(@"[DEBUG] %@", @"Requesting always authorize"); | ||
if ([[NSBundle mainBundle] objectForInfoDictionaryKey:kTiGeolocationUsageDescriptionAlways] || [[NSBundle mainBundle] objectForInfoDictionaryKey:kTiGeolocationUsageDescriptionAlwaysAndWhenInUse]) { | ||
NSLog(@"[DEBUG] %@", @"Requesting always authorize with key set"); | ||
TiThreadPerformOnMainThread(^{ | ||
[[self locationPermissionManager] requestAlwaysAuthorization]; | ||
}, | ||
NO); | ||
} else { | ||
errorMessage = [NSString stringWithFormat:@"The %@ or %@ key must be defined in your tiapp.xml in order to request this permission.", | ||
kTiGeolocationUsageDescriptionAlways, kTiGeolocationUsageDescriptionAlwaysAndWhenInUse]; | ||
} | ||
return; | ||
} | ||
|
||
if (errorMessage != nil) { | ||
NSLog(@"[ERROR] %@", errorMessage); | ||
[self executeAndReleaseCallbackWithCode:(errorMessage == nil) ? 0 : 1 andMessage:errorMessage]; | ||
RELEASE_TO_NIL(errorMessage); | ||
} | ||
} | ||
|
||
#pragma mark Delegates | ||
|
||
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status | ||
{ | ||
NSLog(@"[DEBUG] %@ : %d", @"Auth changed to", status); | ||
|
||
// The new callback for android parity used inside Ti.Geolocation.requestLocationPermissions() | ||
if (authorizationCallback != nil && status != kCLAuthorizationStatusNotDetermined && status != oldStatus) { | ||
|
||
int code = 0; | ||
NSString *errorStr = nil; | ||
|
||
switch (status) { | ||
case kCLAuthorizationStatusAuthorizedAlways: | ||
case kCLAuthorizationStatusAuthorizedWhenInUse: | ||
break; | ||
default: | ||
code = 1; | ||
errorStr = @"The user denied access to use location services."; | ||
} | ||
|
||
TiThreadPerformOnMainThread(^{ | ||
NSMutableDictionary *propertiesDict = [TiUtils dictionaryWithCode:code message:errorStr]; | ||
[propertiesDict setObject:NUMINT([CLLocationManager authorizationStatus]) forKey:@"authorizationStatus"]; | ||
KrollEvent *invocationEvent = [[KrollEvent alloc] initWithCallback:authorizationCallback eventObject:propertiesDict thisObject:self]; | ||
[[authorizationCallback context] enqueue:invocationEvent]; | ||
RELEASE_TO_NIL(invocationEvent); | ||
}, | ||
YES); | ||
|
||
RELEASE_TO_NIL(authorizationCallback); | ||
RELEASE_TO_NIL(errorStr); | ||
RELEASE_TO_NIL(locationPermissionManager); | ||
|
||
oldStatus = status; | ||
} | ||
} | ||
|
||
@end |
Oops, something went wrong.