由于与 ionic://localhost 的不安全连接(在 cordova-ios 上),对地理位置的访问被阻止

Posted

技术标签:

【中文标题】由于与 ionic://localhost 的不安全连接(在 cordova-ios 上),对地理位置的访问被阻止【英文标题】:Access to geolocation was blocked over insecure connection to ionic://localhost (on cordova-ios) 【发布时间】:2020-08-22 09:41:21 【问题描述】:

我正在尝试使用我创建的“location.service”获取移动设备的位置和方向(指南针方向)。它曾经在androidios上都可以工作,现在在ios上,我得到了位置,但是设备方向出错。

[被阻止] 对地理位置的访问因连接不安全而被阻止 到 ionic://localhost。

Geolocation PositionError code: 1, message: "Origin 没有 使用地理定位服务的权限”

我已经在 *.plist 文件上尝试了所有这些:

我正在使用:

@angular/cli 7.3.9

cordova-lib@9.0.1

平台: 安卓8.1.0 ios 5.1.1 插件(缩短): cordova-plugin-ionic-webview 4.1.1 “cordova-plugin-ionic-webview” cordova-plugin-geolocation 4.0.2“地理位置”

当我cordova build ios 时,在我的 iPhone (ios 13.4.1) 上从 Xcode 运行它并检查 Safari 的开发控制台:

位置服务:

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);
    
  

【问题讨论】:

你有什么运气吗?我使用的是普通的 Cordova(无 Ionic),尝试“升级”到 wkwebview 时遇到类似错误“由于与 app://localhost 的不安全连接而阻止了对地理位置的访问”。 我写了我得到的所有东西...@JessePangburn 谢谢!我的问题是在使用 WKWebView 之前我不需要 cordova-plugin-geolocation 插件。添加这个插件解决了这个问题,尽管人们应该知道该插件有一个硬编码的 5 米距离过滤器,这与没有插件时 navigator.geolocation.watchPosition 的工作方式不同。 【参考方案1】:

原来错误消息与设备的位置无关(当我修复位置时,错误仍然存​​在)。方向有点问题,但我有一个答案:

    位置 - 当我请求 .plist 文件中的所有正确权限时,我收到了正确的位置。 Here is a nice explanation 关于权限。顺便说一句,我正在使用cordova-plugin-geolocation。 方向(指南针)-根据“Safari 13 Release Notes”:

在 iOS 上为 DeviceMotionEvent 和 设备方向事件。

一个。 Permission API - 到目前为止,Chrome 和 Safari 只显示“在没有用户手势的情况下询问设备方向”的警告,但在 ios 13+ 上,苹果又迈出了一步,完全阻止了它。 The full w3c discussion。 在下面的最后代码示例中询问权限的正确方法示例。

b.旧的/新的替代方案 (cordova-plugin-device-orientation) - 因为这种行为在应用程序中确实不自然,所以我尝试了一个使用原生资源的旧的已弃用插件,它有效,幸运的是,现在该插件实际上已被弃用!


我的完整代码与后备

    尝试从 deviceready 上的浏览​​器请求位置和方向的许可(适用于 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.")');
      
    );
  

【讨论】:

以上是关于由于与 ionic://localhost 的不安全连接(在 cordova-ios 上),对地理位置的访问被阻止的主要内容,如果未能解决你的问题,请参考以下文章

如何禁止与 http-server npm 的不安全连接?

Firebase 部署的不安全连接错误

SQL双机热备,DTC分配IP能不能与windows集群IP相同,DTC不安装有什么影响?

转:曼弗雷德:你的不安全感,是如何摧毁掉公司的?

转:曼弗雷德:你的不安全感,是如何摧毁掉公司的?

书讯矿工不安全行为传播网络模型及其应用——基于社会接触的视角