Skip to content

'orientation' event firing only on start for Android devices #2323

Open
@pablobertran

Description

@pablobertran

Bug Report

Plugin(s)

@capacitor/[email protected]

Capacitor Version

💊   Capacitor Doctor  💊 

Latest Dependencies:

  @capacitor/cli: 7.0.1
  @capacitor/core: 7.0.1
  @capacitor/android: 7.0.1
  @capacitor/ios: 7.0.1

Installed Dependencies:

  @capacitor/cli: 6.1.2
  @capacitor/core: 6.1.2
  @capacitor/android: 6.1.2
  @capacitor/ios: 6.1.2

[success] iOS looking great! 👌
[success] Android looking great! 👌

Platform(s)

  • Android

Current Behavior

Currently the device orientation event is only being fired once when the app starts.

Expected Behavior

It should fire every time I move the device.

Code Reproduction

Here's a simplified version of our implementation:

import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, ViewChild} from '@angular/core';
import {PluginListenerHandle} from '@capacitor/core';
import {Motion} from "@capacitor/motion";
import {NavController, Platform, ViewDidEnter, ViewWillEnter, ViewWillLeave} from "@ionic/angular";
import {ScreenOrientationService} from "../../services/screen-orientation.service";
import {CameraPreview, CameraPreviewOptions} from '@capacitor-community/camera-preview';
import {map, Observable} from "rxjs";
import {GeoUtilService} from "../../services/geo-utl.service";
import {fromPromise} from "rxjs/internal/observable/innerFrom";
import {FirebaseAnalytics} from "@capacitor-firebase/analytics";

let orientationHandler: PluginListenerHandle;
const STEEPNESS_BORDERS = [30, 35, 40, 180];

@Component({
  selector: 'app-clinometer',
  templateUrl: './clinometer.page.html',
  styleUrls: ['./clinometer.page.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ClinometerPage implements ViewWillEnter, ViewWillEnter, ViewWillLeave, ViewDidEnter {

  currentPosition: any;
  degrees: number = 0;
  degreesAbs: number = 0;
  altitude: number = 0;
  altitudeAccuracy: number = 0;
  latitude: number = 0;
  longitude: number = 0;
  hold: boolean = false;
  steepness: string = '0';
  cameraSteepness: string = '0';
  showCamera: boolean = false;
  isLandscape: boolean = false;
  rotation: number = 0;
  @ViewChild('pageContent') pageContent: ElementRef | undefined;
  @ViewChild('previewCamera') previewCamera: ElementRef | undefined;
  locationEnabled$: Observable<boolean> = fromPromise(this.geoUtils.checkPermissions()).pipe(
    map((permissions) => permissions.location !== 'denied'),
  );

  constructor(
    private platform: Platform,
    private cdr: ChangeDetectorRef,
    private screenOrientationSvc: ScreenOrientationService,
    private navCtrl: NavController,
    private geoUtils: GeoUtilService,
  ) {

  }

  async ionViewDidEnter() {
    
  }

  async ionViewWillEnter() {
    this.screenOrientationSvc.unlock();
    await this.platform.ready();
    if(this.platform.is('ios')) {
      console.log('devicemotion', (DeviceOrientationEvent as any)?.requestPermission);
      let orientationPermission;
      if (DeviceOrientationEvent && typeof (DeviceOrientationEvent as any).requestPermission === 'function') {
        // iOS 13+ needs to request permission
        try {
          // @ts-ignore
          orientationPermission = await DeviceOrientationEvent?.requestPermission();
          if(orientationPermission) {
            orientationPermission = await (DeviceOrientationEvent as any).requestPermission();
          }
        } catch (e) {
          // Handle error
          return;
        }
      }
    }

    orientationHandler = await Motion.addListener('orientation', (orientation) => {
        let baseDegrees;
        if(this.isLandscape) {
          baseDegrees = 90 - Math.abs(orientation.beta) - 90;
        } else {
          baseDegrees = Math.abs(orientation.beta);
        }
        this.rotation = orientation.alpha;
        if(!this.hold) {
          this.degreesAbs = Math.abs(baseDegrees);
          this.degrees = Math.abs(Math.round(baseDegrees));
          this.steepness = STEEPNESS_BORDERS.findIndex(value => this.degrees < value)+'';
          this.cameraSteepness = STEEPNESS_BORDERS.findIndex(value => this.degrees < value)+'';
          this.cdr.detectChanges();
        }
      });
  }

  ionViewWillLeave() {
    this.screenOrientationSvc.lockOrientation('portrait');
  }

}

Other Technical Details

  • Working with WebStorm (latest)
  • Also using these plugins:
    • @capacitor/device
    • @capacitor/filesystem
    • @capacitor/geolocation
    • @capacitor/haptics
    • @capacitor/keyboard
    • @capacitor/network
    • @capacitor/preferences
    • @capacitor/splash
    • @capacitor/status
    • @capgo/nativegeocoder

Additional Context

Funny thing is that it's been working until a few weeks. We just got a report from an Android user that wasn't being able to see the device inclination on his device and are able to reproduce it in all Android devices. But iOS is working just fine.


UPDATE:
Tested on @capacitor/motion@7 and I'm getting the same behaviour. Anyone else experiencing this?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions