Как использовать (угловой) HTTP-клиент в собственной фоновой службе - NativeScript

Как я могу использовать угловой http-клиент в фоновой службе (android).

Моему приложению необходимо отправить данные из фоновой службы на мой сервер.

Я использую 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.info("Background watchLocation error: " + (e.message || e));
                    },
                    {
                        desiredAccuracy: Accuracy.high,
                        updateDistance: 5,
                        updateTime: 5000,
                        minimumUpdateTime: 100
                    });
            }, function (e) {
                console.info("Background enableLocationRequest error: " + (e.message || e));
            });
        },
        onBind: function (intent) {
            console.info("on Bind Services");
        },
        onUnbind: function (intent) {
            console.info('UnBind Service');
        },
        onDestroy: function () {
            geolocation.clearWatch(this.id);
        }
    });
}

Я пробовал два подхода.

(1). Использование инжектора для внедрения моего сервиса

         const injector = Injector.create([ { provide: ExampleService, useClass: ExampleService, deps: [HttpClient] }]);
         const service = injector.get(ExampleService);
         console.info(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.info(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

Итак, в основном первый подход - angular, проблема в том, что я не внедряю все необходимые службы / не знаю, как это сделать.

Второй подход является родным, и проблема в том, что сеть находится в основном потоке. Мне нужно использовать AsyncTask, просто не знаю, как

1
0
1 056
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете попробовать использовать Светоотражающий инжектор, но не забудьте использовать NativeScriptHttpClientModule. Я не пробовал, поэтому не могу сказать, что это сработает.

В итоге я использовал неугловой Http-модуль. Немного взломано не пользоваться услугами, но это работает.

Изменить (июнь / 2019)

В приведенном ниже примере я использовал BrowserXhr из устаревшего пакета @angular/http. Я обновился, чтобы использовать вместо этого частный угловой API. Пример обновлен.

Изменить (апрель / 2019)

В итоге я действительно нуждался в этом, и мне удалось внедрить HttpClient в приложение, отличное от angular. Это также должно работать с фоновыми службами и рабочими.

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.info("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, поэтому вам придется добавить его самостоятельно, если вы собираетесь его использовать. Тем не менее, похоже, что файлы cookie XHR в настоящее время не поддерживаются: 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 Я обновил свой ответ. Таким образом, вы сможете использовать HttpClient Nativescript. Мне удалось использовать HttpClient в пустом приложении с простым TS (не в угловом приложении)

Bass 11.04.2019 04:03
Ответ принят как подходящий

Пожалуйста, посмотрите эту ссылку Как исправить исключение android.os.NetworkOnMainThreadException?

Добавьте следующее в свой собственный код, как вы упомянули в варианте 2. И он должен работать.

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

Это сработало, но кажется хакерским использовать сокеты в основном потоке.

Tinus Jackson 20.06.2018 12:14

Другие вопросы по теме