如何在NativeScript 5和Angular 7中制作Geo-Background-Service

时间:2019-05-25 14:09:27

标签: geolocation nativescript angular7

the GitHub site中的nativescript-geolocation插件在geo location background-service上提供了一个演示,尽管演示工作正常,但是该项目是使用更原始的NativeScript版本构建的,我尝试将其与最新版本进行转换NativeScript(5.4.0)和Angular(7.2.0),但是失败了,如何制作?谢谢!

npm install -g nativescript


cd ~/Desktop
mkdir demo-geo-bks
cd demo-geo-bks
tns create demo-geo-bks --ng

tns plugin add nativescript-toast
tns plugin add nativescript-geolocation

npm install --save tns-platform-declarations 

然后创建一个参考文件:reference.d.ts

/// <reference path="../node_modules/tns-platform-declarations/ios.d.ts" />
/// <reference path="../node_modules/tns-platform-declarations/android.d.ts" />

并修改清单文件,添加权限和服务节点。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="1" android:versionName="1.0">

	<supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true"/>

	  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.PERSISTENT_ACTIVITY" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

	<application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/AppTheme">

		<service android:name="com.nativescript.location.BackgroundService" android:exported="false" />
		<service android:name="com.nativescript.location.BackgroundService26" android:permission="android.permission.BIND_JOB_SERVICE" android:enabled="true" android:exported="false" />

		<activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode" android:theme="@style/LaunchScreenTheme">

			<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />

			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>
		<activity android:name="com.tns.ErrorReportActivity"/>
	</application>
</manifest>

添加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";
import * as Toast from "nativescript-toast";

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) {
                    let toast = Toast.makeText('Background Location: \n' + loc.latitude + ', ' + loc.longitude);
                    toast.show();
                    console.log('Background Location: ' + loc.latitude + ' ' + loc.longitude);
                }
            },
            function (e) {
                console.log("Background watchLocation error: " + (e.message || e));
            },
            {
                desiredAccuracy: Accuracy.high,
                updateDistance: 0,
                updateTime: 1000,
                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;
            },
        });
    }
}

修订组件ts文件:items.component.ts

import { Component, OnInit } from "@angular/core";
import * as geolocation from "nativescript-geolocation";
import { Accuracy } from "tns-core-modules/ui/enums";
import { EventData } from "tns-core-modules/data/observable";
import { Page } from "tns-core-modules/ui/page";
const utils = require("tns-core-modules/utils/utils");
import * as application from "tns-core-modules/application";
import { device } from "tns-core-modules/platform";


let page: Page;
let watchIds = [];
const jobId = 308; // the id should be unique for each background job. We only use one, so we set the id to be the same each time.
declare var com: any;



@Component({
    selector: "ns-items",
    moduleId: module.id,
    templateUrl: "./items.component.html"
})
export class ItemsComponent implements OnInit {

    locations:any;


    constructor() { 


    application.on(application.exitEvent, this._stopBackgroundJob);

    }

    ngOnInit(): void {
    }


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

   startBackgroundTap() {
        if (application.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(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);
            }
        }
    }
    
    stopBackgroundTap() {
        if (application.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);
            }
        }
    }
    
      enableLocationTap() {
        geolocation.isEnabled().then(function (isEnabled) {
            if (!isEnabled) {
                geolocation.enableLocationRequest(false, true).then(function () {
                    console.log("allowed location usage");
                }, function (e) {
                    console.log("Error: " + (e.message || e));
                });
            }
        }, function (e) {
            console.log("Error: " + (e.message || e));
        });
    
    
    }
    
     buttonGetLocationTap() {
        geolocation.getCurrentLocation({
            desiredAccuracy: Accuracy.high,
            maximumAge: 5000,
            timeout: 10000
        }).then(function (loc) {
            if (loc) {
                this.locations.push(loc);
            }
        }, function (e) {
            console.log("Error: " + (e.message || e));
        });
    }
    
    buttonStartTap() {
        try {
            watchIds.push(geolocation.watchLocation(
                function (loc) {
                    if (loc) {
                        this.locations.push(loc);
                    }
                },
                function (e) {
                    console.log("Error: " + e.message);
                },
                {
                    desiredAccuracy: Accuracy.high,
                    updateDistance: 1,
                    updateTime: 3000,
                    minimumUpdateTime: 100
                }));
        } catch (ex) {
            console.log("Error: " + ex.message);
        }
    }
    
     buttonStopTap() {
        let watchId = watchIds.pop();
        while (watchId != null) {
            geolocation.clearWatch(watchId);
            watchId = watchIds.pop();
        }
    }
    
    buttonClearTap() {
       this.locations.splice(0,this.locations.length);
    }




}

修订组件布局文件:items.component.html

<!--
The template defines the view of the component - what is actually rendered.
In NativeScript applications the template is defined with XML using NativeScript UI elements.
It is different from HTML. So instead of <input>, <span>, <div> etc. - we have <TextField>, <Label> and layouts.
The important thing is that although the elements are different - all of the Angular’s template syntax works exactly the same.
So you can still use template expressions, bindings, templates as well as all the built-in directives.
-->

<!--
The ActionBar is the NativeScript common abstraction over the Android ActionBar and iOS NavigationBar.
http://docs.nativescript.org/ui/action-bar
-->
<ActionBar title="My App" class="action-bar">
</ActionBar>

<!--
The GridLayout arranges its child elements in a table structure of rows and columns.
A cell can contain multiple child elements, they can span over multiple rows and columns, 
and even overlap each other. The GridLayout has one column and one row by default.
You can learn more about NativeScript layouts at https://docs.nativescript.org/ui/layout-containers.

These components make use of several CSS class names that are part of the NativeScript
core theme, such as p-20, btn, h2, and list-group. You can view a full list of the
class names available for styling your app at https://docs.nativescript.org/ui/theme.
-->
<GridLayout rows="auto, auto, *, auto">
    <GridLayout row="0" columns="*, *, *, *" >
        <Button text="Enable Location" col="0" textWrap="true" tap="enableLocationTap"></Button>
        <Button text="Get Current Location" col="1" textWrap="true" tap="buttonGetLocationTap"></Button>
        <Button text="Start Monitoring" col="2" textWrap="true" tap="buttonStartTap"></Button>
        <Button text="Stop Monitoring" col="3" textWrap="true" tap="buttonStopTap"></Button>
    </GridLayout>
    <GridLayout row="1" columns="*, *" >
        <Button text="Start Background thread monitoring" col="0" ios:visibility="collapsed" textWrap="true" tap="startBackgroundTap"></Button>
        <Button text="Stop Background thread monitoring" col="1" ios:visibility="collapsed" textWrap="true" tap="stopBackgroundTap"></Button>
    </GridLayout>
    <!-- <ListView row="2" items="{{ locations }}">
        <ListView.itemTemplate>
            <Label text="{{ $value, latitude + ', ' + longitude + ', ' + altitude }}" ></Label>
        </ListView.itemTemplate>
    </ListView> -->
    <Button text="Clear" row="3" tap="buttonClearTap"></Button>
</GridLayout>

package.json

{
  "nativescript": {
    "id": "org.nativescript.demogeobks",
    "tns-android": {
      "version": "5.4.0"
    },
    "tns-ios": {
      "version": "5.4.0"
    }
  },
  "description": "NativeScript Application",
  "license": "SEE LICENSE IN <your-license-filename>",
  "repository": "<fill-your-repository-here>",
  "dependencies": {
    "@angular/animations": "~7.2.0",
    "@angular/common": "~7.2.0",
    "@angular/compiler": "~7.2.0",
    "@angular/core": "~7.2.0",
    "@angular/forms": "~7.2.0",
    "@angular/http": "~7.2.0",
    "@angular/platform-browser": "~7.2.0",
    "@angular/platform-browser-dynamic": "~7.2.0",
    "@angular/router": "~7.2.0",
    "nativescript-angular": "~7.2.0",
    "nativescript-geolocation": "^5.1.0",
    "nativescript-theme-core": "~1.0.4",
    "nativescript-toast": "^2.0.0",
    "reflect-metadata": "~0.1.12",
    "rxjs": "~6.3.0",
    "tns-core-modules": "~5.4.0",
    "tns-platform-declarations": "^5.4.1",
    "zone.js": "~0.8.26"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~7.2.0",
    "@nativescript/schematics": "~0.5.0",
    "@ngtools/webpack": "~7.2.0",
    "nativescript-dev-typescript": "~0.9.0",
    "nativescript-dev-webpack": "~0.22.0"
  },
  "gitHead": "c06800e52ee1a184ea2dffd12a6702aaa43be4e3",
  "readme": "NativeScript Application"
}

最终的项目树可能是这样的,它被顺利编译但没有用。

enter image description here

我也尝试在the Playground Site进行演示,但没有成功。

0 个答案:

没有答案