【问题标题】:How to use (angular) HTTP Client in native background service - NativeScript如何在本机后台服务中使用(角度)HTTP 客户端 - NativeScript
【发布时间】:2018-06-18 06:59:45
【问题描述】:

如何在我的后台服务 (android) 中使用 Angular http 客户端。

我的应用需要将数据从后台服务发送到我的服务器。

我正在使用 NativeScript / Angular。

我的后台服务

declare var android;

if (application.android) {
    (<any>android.app.Service).extend("org.tinus.Example.BackgroundService", {
        onStartCommand: function (intent, flags, startId) {
            this.super.onStartCommand(intent, flags, startId);
            return android.app.Service.START_STICKY;
        },
        onCreate: function () {
            let that = this;

            geolocation.enableLocationRequest().then(function () {
                that.id = geolocation.watchLocation(
                    function (loc) {

                        if (loc) {
                            // should send to server from here

                        }
                    },
                    function (e) {
                        console.log("Background watchLocation error: " + (e.message || e));
                    },
                    {
                        desiredAccuracy: Accuracy.high,
                        updateDistance: 5,
                        updateTime: 5000,
                        minimumUpdateTime: 100
                    });
            }, function (e) {
                console.log("Background enableLocationRequest error: " + (e.message || e));
            });
        },
        onBind: function (intent) {
            console.log("on Bind Services");
        },
        onUnbind: function (intent) {
            console.log('UnBind Service');
        },
        onDestroy: function () {
            geolocation.clearWatch(this.id);
        }
    });
}

我尝试了两种方法。

(1)。使用 Injector 注入我的服务

         const injector = Injector.create([ { provide: ExampleService, useClass: ExampleService, deps: [HttpClient] }]);
         const service = injector.get(ExampleService);
         console.log(service.saveDriverLocation); // This prints
         service.saveDriverLocation(new GeoLocation(loc.latitude, loc.longitude, loc.horizontalAccuracy, loc.altitude), ['id']); // This complains 

(1) 的问题

System.err: TypeError: Cannot read property 'post' of undefined

(2)。使用本机代码

     let url = new java.net.URL("site/fsc");
     let connection = null;
     try {
          connection = url.openConnection();
     } catch (error) {
           console.log(error);
     }

     connection.setRequestMethod("POST");
     let out = new java.io.BufferedOutputStream(connection.getOutputStream());
     let writer = new java.io.BufferedWriter(new java.io.OutputStreamWriter(out, "UTF-8"));
     let data = 'mutation NewDriverLoc{saveDriverLocation(email:"' + (<SystemUser>JSON.parse(getString('User'))).email + '",appInstanceId:' + (<ApplicationInstance>JSON.parse(getString('appInstance'))).id + ',geoLocation:{latitude:' + loc.latitude + ',longitude:' + loc.longitude + ',accuracy:' + loc.horizontalAccuracy + '}){id}}';
     writer.write(data);
     writer.flush();
     writer.close();
     out.close();
     connection.connect();

(2) 的问题

System.err: Caused by: android.os.NetworkOnMainThreadException

所以基本上第一种方法是有角度的,问题是我没有注入所有需要的服务/不确定如何。

第二种方法是原生的,问题是网络在主线程上。我需要使用 AsyncTask 只是不知道如何

【问题讨论】:

    标签: android angular typescript nativescript


    【解决方案1】:

    请看这个链接 How do I fix android.os.NetworkOnMainThreadException?

    将以下内容添加到您在选项 2 中提到的本机代码中。它应该可以工作

    let policy = new 
    android.os.StrictMode.ThreadPolicy.Buiilder().permitAll().build();
    andriod.os.StrictMode.setThreadPolicy(policy);
    

    【讨论】:

    • 这行得通,但是在主线程上使用套接字感觉很麻烦
    【解决方案2】:

    您可以尝试使用ReflectiveInjector,但请记住使用 NativeScriptHttpClientModule。我还没试过,所以我不能说它会起作用。

    我最终使用的是non-angular Http module。不使用服务有点hacky,但它可以工作。

    编辑(2019 年 6 月)

    在下面的示例中,我使用了已弃用的 @angular/http 包中的 BrowserXhr。我已经更新为使用私有 Angular API。示例已更新。

    编辑(2019 年 4 月)

    所以我最终实际上需要这个并设法将 HttpClient 注入到非角度应用程序中。这也应该适用于后台服务和工作人员。

    import { HttpBackend, HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HTTP_INTERCEPTORS, XhrFactory, ɵangular_packages_common_http_http_d as BrowserXhr, ɵHttpInterceptingHandler } from "@angular/common/http";
    import { Injector } from '@angular/core';
    import { NSFileSystem } from "nativescript-angular/file-system/ns-file-system";
    import { NsHttpBackEnd } from "nativescript-angular/http-client/ns-http-backend";
    import { Observable } from 'rxjs';
    
    export class TestInterceptor implements HttpInterceptor {
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            console.log("intercepted", req);
            return next.handle(req);
        }
    
    
    }
    
    const httpClientInjector = Injector.create([
        {
            provide: HttpClient, useClass: HttpClient, deps: [
                HttpHandler
            ]
        },
        { provide: HttpHandler, useClass: ɵHttpInterceptingHandler, deps: [HttpBackend, Injector] },
        { provide: HTTP_INTERCEPTORS, useClass: TestInterceptor, multi: true, deps: [] }, // remove or copy this line to remove/add more interceptors
        { provide: HttpBackend, useExisting: NsHttpBackEnd },
        { provide: NsHttpBackEnd, useClass: NsHttpBackEnd, deps: [XhrFactory, NSFileSystem] },
        { provide: XhrFactory, useExisting: BrowserXhr },
        { provide: BrowserXhr, useClass: BrowserXhr, deps: [] },
        { provide: NSFileSystem, useClass: NSFileSystem, deps: [] }
    ]);
    
    export const httpClient = httpClientInjector.get(HttpClient);
    

    请注意,我也在利用拦截器。

    这个实现缺少HttpClientXsrfModule,所以如果你打算使用它,你必须自己添加它。也就是说,目前似乎不支持 XHR cookie:https://github.com/NativeScript/NativeScript/issues/2424

    如果您想使用以下服务:

    export class MyService {
        constructor(private http: HttpClient) { }
    }
    

    您可以在数组顶部(Injector.create[ 之后)添加以下内容:

    { provide: MyService, useClass: MyService, deps: [HttpClient] }(请记住,deps 必须按照构造函数要求的顺序!)

    然后,您可以致电const myService = httpClientInjector.get(MyService); 获得服务

    【讨论】:

    • @TinusJackson 我已经更新了我的回复。这样你应该可以使用 Nativescript 的 HttpClient。我设法在带有普通 TS 的空白应用程序上使用 HttpClient(而不是在 Angular 应用程序中)
    猜你喜欢
    • 2022-11-10
    • 1970-01-01
    • 2018-11-17
    • 2019-06-21
    • 2016-11-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-28
    • 2018-01-20
    相关资源
    最近更新 更多