简体   繁体   English

如何使地理定位后台服务在我的nativescript-angular应用程序中工作?

[英]How to make geolocation background services work in my nativescript-angular app?

I'm using this geolocation-plugin ( https://github.com/NativeScript/nativescript-geolocation/tree/e125998c07ced42a215aca1a8feac1b7dbe7b6d6 ) to get constant location updates while app is in the background. 我正在使用此geolocation-plugin( https://github.com/NativeScript/nativescript-geolocation/tree/e125998c07ced42a215aca1a8feac1b7dbe7b6d6 )在应用程序处于后台时获取恒定的位置更新。

I tried using the code in the demo, but I'm not figuring out how to make it work. 我尝试在演示中使用代码,但是我没有弄清楚如何使其工作。

I would like the user to press a button and the app to start monitoring his location, even if the app goes in the background. 我希望用户按下一个按钮,然后该应用开始监视他的位置,即使该应用在后台运行也是如此。

home.component.ts home.component.ts

import { Component, OnInit, AfterViewInit } from "@angular/core";
import { RadSideDrawer } from "nativescript-ui-sidedrawer";
import { getRootView } from "tns-core-modules/application";
import * as app from "tns-core-modules/application";
const utils = require("tns-core-modules/utils/utils");
import { device } from "tns-core-modules/platform";


//import { GeolocationService } from "../services/geolocation/geolocation.service";


@Component({
    selector: "Home",
    moduleId: module.id,
    templateUrl: "./home.component.html"
})
export class HomeComponent implements OnInit {

    public drawer: RadSideDrawer;
    public buttonText = "Start";

    locations = [];
    watchIds = [];
    jobId = 308;

    constructor(
        public geolocationService: GeolocationService,
    ) {}

    ngOnInit(): void {
        app.on(app.exitEvent, this._stopBackgroundJob);
    }


    ngAfterViewInit() {
        this.drawer = <RadSideDrawer>getRootView();
        this.drawer.gesturesEnabled = true;
    }

    onDrawerButtonTap(): void {
        const sideDrawer = <RadSideDrawer>app.getRootView();
        sideDrawer.showDrawer();
    }


    _stopBackgroundJob() {
        if (app.android) {
            let context = utils.ad.getApplicationContext();
            const jobScheduler = context.getSystemService((<any>android.content.Context).JOB_SCHEDULER_SERVICE);
            if (jobScheduler.getPendingJob(this.jobId) !== null) {
                jobScheduler.cancel(this.jobId);
                console.log(`Job Canceled: ${this.jobId}`);
            }
        }
    }

    checkLoc(){
        this.geolocationService.buttonGetLocationTap()
    }


    _onGeolocationService(){
        this.geolocationService.enableLocation()
        .then(result => {
            this.geolocationService.monitorLocation();

            if(this.geolocationService.locationMonitor === true){
                this.buttonText = "Stop";
            } else {
                this.buttonText = "Start";
            }

        })
    }

    public startBackgroundTap() {
        if (app.android) {
            let context = utils.ad.getApplicationContext();
            if (device.sdkVersion >= "26") {
                const jobScheduler = context.getSystemService((<any>android.content.Context).JOB_SCHEDULER_SERVICE);
                const component = new android.content.ComponentName(context, com.nativescript.location.BackgroundService26.class);
                const builder = new (<any>android.app).job.JobInfo.Builder(this.jobId, component);
                builder.setOverrideDeadline(0);
                return jobScheduler.schedule(builder.build());
            } else {
                let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class);
                context.startService(intent);
            }
        }
    }

    public stopBackgroundTap() {
        if (app.android) {
            if (device.sdkVersion >= "26") {
                this._stopBackgroundJob();
            } else {
                let context = utils.ad.getApplicationContext();
                let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class);
                context.stopService(intent);
            }
        }
    }

}

geolocation.service.ts geolocation.service.ts

import { Injectable } from '@angular/core';
import * as geolocation from "nativescript-geolocation";
import { Accuracy } from "tns-core-modules/ui/enums";

@Injectable({
  providedIn: 'root'
})
export class GeolocationService {

  locations= [];
  watchIds = [];

  constructor() { }

  public enableLocation() {
    return geolocation.enableLocationRequest();
  }

  public checkIfLocationIsEnabled() {
    geolocation.isEnabled()
    .then(function (isEnabled) {
      if(isEnabled) {
        return true;
      } else {
        return false;
      }
    })
  }

  public buttonGetLocationTap() {
    let that = this;
    geolocation.getCurrentLocation({
        desiredAccuracy: Accuracy.high,
        iosAllowsBackgroundLocationUpdates: true,
        iosPausesLocationUpdatesAutomatically: false,
        iosOpenSettingsIfLocationHasBeenDenied: true,
        maximumAge: 5000,
        timeout: 10000,
        updateTime: 10000,
    }).then(function (loc) {
      console.log(loc["latitude"], loc["longitude"])  
      if (loc) {
            that.locations.push(loc);
        }
    }, function (e) {
        console.log("Error: " + (e.message || e));
    });
}

  public buttonStartTap() {
      try {
          let that = this;
          that.watchIds.push(geolocation.watchLocation(
              function (loc) {
                  if (loc) {
                      that.locations.push(loc);
                  }
              },
              function (e) {
                  console.log("Error: " + e.message);
              },
              {
                  desiredAccuracy: Accuracy.high,
                  iosAllowsBackgroundLocationUpdates: true,
                  iosPausesLocationUpdatesAutomatically: false,
                  iosOpenSettingsIfLocationHasBeenDenied: true,
                  maximumAge: 7000,
                  timeout: 9000,
                  updateTime: 9000,
              }));
      } catch (ex) {
          console.log("Error: " + ex.message);
      }
  }

  public buttonStopTap() {
    let watchId = this.watchIds.pop();
    while (watchId != null) {
        geolocation.clearWatch(watchId);
        watchId = this.watchIds.pop();
    }
  }


  public buttonClearTap() {
    this.locations.splice(0, this.locations.length);
  }
}

background.service.ts background.service.ts

import * as geolocation from "nativescript-geolocation";
import { Accuracy } from "tns-core-modules/ui/enums";
import * as application from "tns-core-modules/application";
import { device } from "tns-core-modules/platform";

let watchId;

function _clearWatch() {
    if (watchId) {
        geolocation.clearWatch(watchId);
        watchId = null;
    }
}

function _startWatch() {
    geolocation.enableLocationRequest().then(function () {
        _clearWatch();
        watchId = geolocation.watchLocation(
            function (loc) {
                if (loc) {
                    console.log('Background Location: ' + loc.latitude + ' ' + loc.longitude);
                }
            },
            function (e) {
                console.log("Background watchLocation error: " + (e.message || e));
            },
            {
                desiredAccuracy: Accuracy.high,
                updateDistance: 1.0,
                updateTime: 3000,
                minimumUpdateTime: 100
            });
    }, function (e) {
        console.log("Background enableLocationRequest error: " + (e.message || e));
    });
}

application.on(application.exitEvent, _clearWatch);

if (application.android) {
    if (device.sdkVersion < "26") {
        (<any>android.app.Service).extend("com.nativescript.location.BackgroundService", {
            onStartCommand: function (intent, flags, startId) {
                this.super.onStartCommand(intent, flags, startId);
                return android.app.Service.START_STICKY;
            },
            onCreate: function () {
                _startWatch();
            },
            onBind: function (intent) {
                console.log("on Bind Services");
            },
            onUnbind: function (intent) {
                console.log('UnBind Service');
            },
            onDestroy: function () {
                console.log('service onDestroy');
                _clearWatch();
            }
        });
    } else {
        (<any>android.app).job.JobService.extend("com.nativescript.location.BackgroundService26", {
            onStartJob() {
                console.log('service onStartJob');
                _startWatch();
                return true;
            },
            onStopJob(jobParameters: any) {
                console.log('service onStopJob');
                this.jobFinished(jobParameters, false);
                _clearWatch();
                return false;
            },
        });
    }
}

Firstly, there is a problem with the 'com' namespace as it says "Property 'nativescript' does not exist on type 'typeof com' ". 首先,'com'名称空间存在问题,因为它说“类型'typeof com'上不存在属性'nativescript'”。 The problem appears in the home.component.ts on these 3 lines: 该问题出现在home.component.ts的以下三行中:

const component = new android.content.ComponentName(context, com.nativescript.location.BackgroundService26.class); const component = new android.content.ComponentName(context,com.nativescript.location.BackgroundService26.class); let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class); let intent = new android.content.Intent(context,com.nativescript.location.BackgroundService.class); let intent = new android.content.Intent(context, com.nativescript.location.BackgroundService.class); let intent = new android.content.Intent(context,com.nativescript.location.BackgroundService.class);

Secondly, I don't know what is the purpose of background-service as it i not used anywhere in the demo (or maybe it is, but in a way that I'm not familiar with). 其次,我不知道后台服务的目的是什么,因为我没有在演示中的任何地方使用后台服务(或者也许是,但是我不熟悉)。

Thank you! 谢谢!

"Property 'nativescript' does not exist on type 'typeof com' " “类型为'typeof com'的属性'nativescript'不存在”

It's simple TypeScript declaration error, casting it to any may solve your issue. 这是简单的TypeScript声明错误,将其强制转换为任何类型都可以解决您的问题。

const component = new android.content.ComponentName(context, (com as any).nativescript.location.BackgroundService26.class); 
let intent = new android.content.Intent(context, (com as any).nativescript.location.BackgroundService.class); 
let intent = new android.content.Intent(context, (com as any).nativescript.location.BackgroundService.class);

As you could see in the demo app, declare var com: any; 在演示应用程序中可以看到, declare var com: any; serves the same purpose. 具有相同的目的。 Alternatively you may declare proper typings if you are familiar with TypeScript. 另外,如果您熟悉TypeScript,则可以声明正确的类型。

Secondly, I don't know what is the purpose of background-service 其次,我不知道后台服务的目的是什么

I think we discussed this already in a different thread, background service is used when you want to run some tasks even when your app is not running. 我认为我们已经在另一个线程中讨论了这一点,即使您的应用程序未运行,当您要运行某些任务时,也会使用后台服务。

The class you are using above com.nativescript.location.BackgroundService is from that file ( background-service.ts ). 您在com.nativescript.location.BackgroundService上方使用的类来自该文件( background-service.ts )。 The same class should be declared in AndroidManifest.xml too. 同样的类也应该在AndroidManifest.xml中声明。

Edit: 编辑:

Sounds like you didn't update your webpack.config.js with entry of background-service.ts file. 听起来您没有使用background-service.ts文件的条目来更新webpack.config.js

// Add your custom Activities, Services and other Android app components here.
const appComponents = [
    "tns-core-modules/ui/frame",
    "tns-core-modules/ui/frame/activity",
     resolve(__dirname, "src/path/to/background-service"),
];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有办法为nativescript-angular应用添加轮播? - is there a way to add carousel for nativescript-angular app? 在nativescript-angular应用中创建Spinner下拉列表 - Create Spinner dropdown list in nativescript-angular app 如何在 nativescript-angular 中为图像做 http post - How to do http post for image in nativescript-angular 为什么我在nativescript-angular app中为application.android.context获取未定义? - Why do I get undefined for application.android.context in nativescript-angular app? 找不到模块:“ nativescript-angular / http”,相对于:app / tns_modules / - Failed to find module: “nativescript-angular/http”, relative to: app/tns_modules/ Android上带有Angular 2的Nativescript,如何关闭我的应用程序? - Nativescript with Angular 2 on Android, how to close my app? 如何使我的应用程序在后台运行? - How can i make my app to work in background? 当我杀死自己的应用程序时,如何确保后台服务不会继续运行? - How do I make sure that my background services don't keep running when I kill my own app? Nativescript如何在后台发出http请求 - Nativescript how to make http requests in the background 后台地理定位在后台的 ionic 3 中不起作用 - Background geolocation not work in ionic 3 in background
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM