由于与 ionic://localhost 的不安全连接(在 cordova-ios 上),对地理定位的访问被阻止
Access to geolocation was blocked over insecure connection to ionic://localhost (on cordova-ios)
我正在尝试使用我创建的 "location.service" 获取移动设备的位置和方向(罗盘航向)。它曾经在 android 和 ios 上工作,现在在 ios 上工作,我得到了位置,但设备方向错误。
[blocked] Access to geolocation was blocked over insecure connection
to ionic://localhost.
Geolocation PositionError {code: 1, message: "Origin does not have
permission to use Geolocation service"
我已经在 *.plist 文件上尝试了所有这些:
我正在使用:
- @angular/cli7.3.9
cordova-lib@9.0.1
- 平台:
- android8.1.0
- ios 5.1.1
- 插件(缩短):
- cordova-plugin-ionic-webview 4.1.1 "cordova-plugin-ionic-webview"
- cordova-plugin-geolocation 4.0.2 "Geolocation"
当我在 iPhone (ios 13.4.1) 上 cordova build ios
, 运行 它来自 Xcode 并检查 Safari 的开发控制台:
location.service:
import {Injectable} from '@angular/core';
import {BehaviorSubject, combineLatest, fromEvent, Observable, of, timer} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {map, switchMap} from 'rxjs/operators';
import { Globals } from '../globals';
export interface DefiLocation {
accuracy: number;
altitude: number;
altitudeAccuracy: number;
heading: number;
latitude: number;
longitude: number;
speed: number;
compass: number;
}
@Injectable({
providedIn: 'root'
})
export class LocationService {
errorMessage$: string;
currentLocation$: BehaviorSubject<{
accuracy?: number,
altitude: number,
altitudeAccuracy: number,
heading: number,
latitude: number,
longitude: number,
speed: number
}> = new BehaviorSubject({
accuracy: 0,
altitude: 0,
altitudeAccuracy: 0,
heading: 0,
latitude: 32.5,
longitude: 35,
speed: 0,
});
currentCompass$: BehaviorSubject<number> = new BehaviorSubject(0);
currentCompass: number = 0;
currentPosition: {
accuracy: 0,
altitude: 0,
altitudeAccuracy: 0,
heading: 0,
latitude: 32.5,
longitude: 35,
speed: 0,
};
locationTimer;
sendLocationError: boolean = true;
constructor(public globals: Globals) {
this.isCurrentPosition$.next(true);
this.trackMe();
}
private trackMe() {
if (this.globals.iphone) {
window.addEventListener('deviceorientation', (event) => {
this.currentCompass$.next(Math.round(event['webkitCompassHeading']));
});
// }
} else {
window.addEventListener('deviceorientationabsolute', (event) => {
this.currentCompass$.next(360 - Math.round(event['alpha']));
}, true);
}
if (navigator.geolocation) {
this.locationTimer = timer(0, 100).subscribe(tick => {
navigator.geolocation.getCurrentPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
console.log(err);
this.errorMessage$ = err.message;
console.log(this.errorMessage$);
}, {
enableHighAccuracy: true
});
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}
getCurrentLocation$(): Observable<DefiLocation> {
return combineLatest(this.currentCompass$.asObservable(), this.currentLocation$.asObservable())
.pipe(
map(([compass, location]) => {
return {
longitude: location.longitude,
latitude: location.latitude,
accuracy: location.accuracy,
altitude: location.altitude,
altitudeAccuracy: location.altitudeAccuracy,
heading: location.heading,
speed: location.speed,
compass
};
}
));
}
sendError(error) {
if (this.sendLocationError) {
this.sendLocationError = false;
window['cordova'].plugins.firebase.analytics.logEvent('user_location_failed', {param1: error});
setTimeout(function() { this.sendLocationError = true; }, 5000);
}
}
}
原来错误消息与设备的位置无关(当我修复位置时错误仍然存在)。方向有点问题,但我有一个答案:
- 位置 - 当我请求 .plist 文件中的所有正确权限时,我收到了正确的位置。 Here is a nice explanation about the permissions. BTW, i'm using cordova-plugin-geolocation.
- 方位(罗盘)-根据“Safari 13 Release Notes”:
Added a permission API on iOS for DeviceMotionEvent and
DeviceOrientationEvent.
一个。权限 API - Up-until 现在,Chrome 和 Safari 只显示关于“在没有用户手势的情况下询问设备方向”的警告,但是在 ios 13+ 上苹果又采取了一步并且完全阻止了它。 The full w3c discussion。 在下面的 last 代码示例中请求权限的正确方法示例。
b。 old/new 替代方案 (cordova-plugin-device-orientation) - 因为这种行为在应用程序中确实不自然,所以我尝试了一个使用本机资源的旧的已弃用插件,它起作用了,幸运的是,现在该插件实际上未被弃用!
我的带有回退的完整代码
- 尝试在设备就绪时向浏览器请求位置和方向许可(适应 android 和 ios)。
- 如果没有,请尝试 orientation-plugin(本机资源)。
- 如果不是,则在 ios13+ 网络协议状态下请求用户手势许可。
此 运行 在设备上就绪:
private trackMe() {
// compass listener (also ios13+ fallback at "compassPremissioniOS13" funtion)
if (typeof DeviceOrientationEvent['requestPermission'] !== 'function') {
const deviceOrientationLestener = (event) => {
if (this.globals.iphone) {
this.currentCompass$.next(event['webkitCompassHeading']);
} else {
if (event.absolute) {
this.currentCompass$.next(360 - event.alpha);
} else {
window.removeEventListener('deviceorientation', deviceOrientationLestener);
window.addEventListener('deviceorientationabsolute', (eventB) => {
this.currentCompass$.next(360 - eventB['alpha']);
}, true);
}
}
};
window.addEventListener('deviceorientation', deviceOrientationLestener);
} else {
document.addEventListener('deviceready', () => {
navigator['compass'].watchHeading((head) => {
this.currentCompass$.next(head.trueHeading);
}, (error) => console.log(error), {frequency: 10});
}, false);
}
// GET LOCATION - energy saving and preformance inhancing for mobile, dumm and cyclic for desktop.
if (this.globals.cordova) {
document.addEventListener('deviceready', () => {
if (navigator.geolocation) {
navigator.geolocation.watchPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
this.errorMessage$ = err.message;
}, {
enableHighAccuracy: true
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}, false);
} else {
if (navigator.geolocation) { // fallback for desktop testing
this.locationTimer = timer(0, 100).subscribe(tick => {
navigator.geolocation.getCurrentPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
this.errorMessage$ = err.message;
}, {
enableHighAccuracy: true
});
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}
}
用户按下导航按钮时 运行 秒:
compassPremissioniOS13$() {
return new Promise((resolve, reject) => {
if (navigator.geolocation) {
if (typeof DeviceOrientationEvent['requestPermission'] === 'function') {
DeviceOrientationEvent['requestPermission']()
.then(permissionState => {
if (permissionState === 'granted') {
window.addEventListener('deviceorientation', (event) => {
this.currentCompass$.next(event['webkitCompassHeading']);
});
resolve('User accepted');
} else {
reject('User declined');
}
})
.catch(console.error);
}
} else {
alert('deviceorientation is not supported by this browser.');
this.sendError('deviceorientation = null ("deviceorientation is not supported by this browser.")');
}
});
}
我正在尝试使用我创建的 "location.service" 获取移动设备的位置和方向(罗盘航向)。它曾经在 android 和 ios 上工作,现在在 ios 上工作,我得到了位置,但设备方向错误。
[blocked] Access to geolocation was blocked over insecure connection to ionic://localhost.
Geolocation PositionError {code: 1, message: "Origin does not have permission to use Geolocation service"
我已经在 *.plist 文件上尝试了所有这些:
我正在使用:
- @angular/cli7.3.9
cordova-lib@9.0.1
- 平台:
- android8.1.0
- ios 5.1.1
- 插件(缩短):
- cordova-plugin-ionic-webview 4.1.1 "cordova-plugin-ionic-webview"
- cordova-plugin-geolocation 4.0.2 "Geolocation"
- 平台:
当我在 iPhone (ios 13.4.1) 上 cordova build ios
, 运行 它来自 Xcode 并检查 Safari 的开发控制台:
location.service:
import {Injectable} from '@angular/core';
import {BehaviorSubject, combineLatest, fromEvent, Observable, of, timer} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {map, switchMap} from 'rxjs/operators';
import { Globals } from '../globals';
export interface DefiLocation {
accuracy: number;
altitude: number;
altitudeAccuracy: number;
heading: number;
latitude: number;
longitude: number;
speed: number;
compass: number;
}
@Injectable({
providedIn: 'root'
})
export class LocationService {
errorMessage$: string;
currentLocation$: BehaviorSubject<{
accuracy?: number,
altitude: number,
altitudeAccuracy: number,
heading: number,
latitude: number,
longitude: number,
speed: number
}> = new BehaviorSubject({
accuracy: 0,
altitude: 0,
altitudeAccuracy: 0,
heading: 0,
latitude: 32.5,
longitude: 35,
speed: 0,
});
currentCompass$: BehaviorSubject<number> = new BehaviorSubject(0);
currentCompass: number = 0;
currentPosition: {
accuracy: 0,
altitude: 0,
altitudeAccuracy: 0,
heading: 0,
latitude: 32.5,
longitude: 35,
speed: 0,
};
locationTimer;
sendLocationError: boolean = true;
constructor(public globals: Globals) {
this.isCurrentPosition$.next(true);
this.trackMe();
}
private trackMe() {
if (this.globals.iphone) {
window.addEventListener('deviceorientation', (event) => {
this.currentCompass$.next(Math.round(event['webkitCompassHeading']));
});
// }
} else {
window.addEventListener('deviceorientationabsolute', (event) => {
this.currentCompass$.next(360 - Math.round(event['alpha']));
}, true);
}
if (navigator.geolocation) {
this.locationTimer = timer(0, 100).subscribe(tick => {
navigator.geolocation.getCurrentPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
console.log(err);
this.errorMessage$ = err.message;
console.log(this.errorMessage$);
}, {
enableHighAccuracy: true
});
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}
getCurrentLocation$(): Observable<DefiLocation> {
return combineLatest(this.currentCompass$.asObservable(), this.currentLocation$.asObservable())
.pipe(
map(([compass, location]) => {
return {
longitude: location.longitude,
latitude: location.latitude,
accuracy: location.accuracy,
altitude: location.altitude,
altitudeAccuracy: location.altitudeAccuracy,
heading: location.heading,
speed: location.speed,
compass
};
}
));
}
sendError(error) {
if (this.sendLocationError) {
this.sendLocationError = false;
window['cordova'].plugins.firebase.analytics.logEvent('user_location_failed', {param1: error});
setTimeout(function() { this.sendLocationError = true; }, 5000);
}
}
}
原来错误消息与设备的位置无关(当我修复位置时错误仍然存在)。方向有点问题,但我有一个答案:
- 位置 - 当我请求 .plist 文件中的所有正确权限时,我收到了正确的位置。 Here is a nice explanation about the permissions. BTW, i'm using cordova-plugin-geolocation.
- 方位(罗盘)-根据“Safari 13 Release Notes”:
Added a permission API on iOS for DeviceMotionEvent and DeviceOrientationEvent.
一个。权限 API - Up-until 现在,Chrome 和 Safari 只显示关于“在没有用户手势的情况下询问设备方向”的警告,但是在 ios 13+ 上苹果又采取了一步并且完全阻止了它。 The full w3c discussion。 在下面的 last 代码示例中请求权限的正确方法示例。
b。 old/new 替代方案 (cordova-plugin-device-orientation) - 因为这种行为在应用程序中确实不自然,所以我尝试了一个使用本机资源的旧的已弃用插件,它起作用了,幸运的是,现在该插件实际上未被弃用!
我的带有回退的完整代码
- 尝试在设备就绪时向浏览器请求位置和方向许可(适应 android 和 ios)。
- 如果没有,请尝试 orientation-plugin(本机资源)。
- 如果不是,则在 ios13+ 网络协议状态下请求用户手势许可。
此 运行 在设备上就绪:
private trackMe() {
// compass listener (also ios13+ fallback at "compassPremissioniOS13" funtion)
if (typeof DeviceOrientationEvent['requestPermission'] !== 'function') {
const deviceOrientationLestener = (event) => {
if (this.globals.iphone) {
this.currentCompass$.next(event['webkitCompassHeading']);
} else {
if (event.absolute) {
this.currentCompass$.next(360 - event.alpha);
} else {
window.removeEventListener('deviceorientation', deviceOrientationLestener);
window.addEventListener('deviceorientationabsolute', (eventB) => {
this.currentCompass$.next(360 - eventB['alpha']);
}, true);
}
}
};
window.addEventListener('deviceorientation', deviceOrientationLestener);
} else {
document.addEventListener('deviceready', () => {
navigator['compass'].watchHeading((head) => {
this.currentCompass$.next(head.trueHeading);
}, (error) => console.log(error), {frequency: 10});
}, false);
}
// GET LOCATION - energy saving and preformance inhancing for mobile, dumm and cyclic for desktop.
if (this.globals.cordova) {
document.addEventListener('deviceready', () => {
if (navigator.geolocation) {
navigator.geolocation.watchPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
this.errorMessage$ = err.message;
}, {
enableHighAccuracy: true
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}, false);
} else {
if (navigator.geolocation) { // fallback for desktop testing
this.locationTimer = timer(0, 100).subscribe(tick => {
navigator.geolocation.getCurrentPosition((position) => {
this.currentLocation$.next(position.coords);
this.isCurrentPosition$.next(true);
this.sendLocationError = true;
}, (err) => {
this.isCurrentPosition$.next(false);
this.sendError(err.message);
this.errorMessage$ = err.message;
}, {
enableHighAccuracy: true
});
});
} else {
alert('Geolocation is not supported by this browser.');
this.sendError('navigator.geolocation = null ("Geolocation is not supported by this browser.")');
}
}
}
用户按下导航按钮时 运行 秒:
compassPremissioniOS13$() {
return new Promise((resolve, reject) => {
if (navigator.geolocation) {
if (typeof DeviceOrientationEvent['requestPermission'] === 'function') {
DeviceOrientationEvent['requestPermission']()
.then(permissionState => {
if (permissionState === 'granted') {
window.addEventListener('deviceorientation', (event) => {
this.currentCompass$.next(event['webkitCompassHeading']);
});
resolve('User accepted');
} else {
reject('User declined');
}
})
.catch(console.error);
}
} else {
alert('deviceorientation is not supported by this browser.');
this.sendError('deviceorientation = null ("deviceorientation is not supported by this browser.")');
}
});
}