transistorsoft / cordova-background-geolocation-SampleApp

Cordova Background Geolocation Sample Application
https://www.transistorsoft.com/shop/products/cordova-background-geolocation
MIT License
122 stars 78 forks source link

It shows only two log. #107

Closed AlexTerry1024 closed 6 years ago

AlexTerry1024 commented 6 years ago

this.bgGeo.ready({ // Geolocation config reset:true, desiredAccuracy: this.bgGeo.DESIRED_ACCURACY_HIGH, distanceFilter: 10, stationaryRadius: 0, stopOnStationary:false, // Activity Recognition config locationUpdateInterval: 3000, activityRecognitionInterval: 10000, // Application config debug: true, // <-- Debug sounds & notifications. startOnBoot: false, foregroundService: true // HTTP / SQLite config }, function(state) { // This callback is executed when the plugin is ready to use. console.log("BackgroundGeolocation ready: ", state); if (!state.enabled) { context.bgGeo.start(); } });

AlexTerry1024 commented 6 years ago

My Device (Hwawei P10 lite, CPU : Kirin658, RAM 3.0GB, )

christocracy commented 6 years ago

Because you haven't configured logLevel

AlexTerry1024 commented 6 years ago

Please explain with logLevel with sample code.

Thanks

christocracy commented 6 years ago

See wiki of the plugin repo. Debugging

christocracy commented 6 years ago

Are you reading the plugin documentation

You find much documentation of the plugin here at the SampleApp repo.

AlexTerry1024 commented 6 years ago

Then why doesn't it show gps icon?

christocracy commented 6 years ago

See wiki Philosophy of Operation

AlexTerry1024 commented 6 years ago

Yes, Just check.

One more question.

There is a way to capture all while the client stop manually?

christocracy commented 6 years ago

stopOnTerminate: false. Give the plugin an #url so it can continue to post locations to your server.

AlexTerry1024 commented 6 years ago

For url, I can use fake url?

christocracy commented 6 years ago

The sample app is already configured to post to my demo server.

The url is not required

AlexTerry1024 commented 6 years ago

Okay, Let me try and update you. Thanks.

AlexTerry1024 commented 6 years ago

It is same

AlexTerry1024 commented 6 years ago

import { Component, ViewChild, ElementRef } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular';

import { Media, MediaObject } from '@ionic-native/media'; import { File } from '@ionic-native/file'; import { SQLite, SQLiteObject } from '@ionic-native/sqlite'; import { Http,Headers } from '@angular/http'; import { Storage } from '@ionic/storage'; import { Shoudios } from '../../model/Shoudios'; import { PhotoItem } from '../../model/PhotoItem'; import { VideoEditor, CreateThumbnailOptions } from '@ionic-native/video-editor'; import { FileTransfer, FileTransferObject } from '@ionic-native/file-transfer'; import { Platform , AlertController} from 'ionic-angular'; import { DeviceOrientation, DeviceOrientationCompassHeading } from '@ionic-native/device-orientation'; import { Slides } from 'ionic-angular'; import { LocalNotifications } from '@ionic-native/local-notifications';

import as L from 'leaflet'; import 'leaflet.markercluster'; import 'leaflet-rotatedmarker'; import { StatusBar } from '@ionic-native/status-bar'; import as $ from 'jquery'; import { HTTP } from '@ionic-native/http'; import { InAppBrowser } from '@ionic-native/in-app-browser'; import 'rxjs/add/operator/retry'; import 'rxjs/add/operator/timeout'; import 'rxjs/add/operator/delay'; import 'rxjs/add/operator/map'; import { Badge } from '@ionic-native/badge'; import { Toast } from '@ionic-native/toast';

/**

@IonicPage({ name: 'route-player-page' }) @Component({ selector: 'page-route-player', templateUrl: 'route-player.html', }) export class RoutePlayerPage { @ViewChild('route_player_map') mapContainer: ElementRef;

@ViewChild(Slides) minimize_title: Slides;

audioFile : MediaObject;

nRouteID : number = 0;
audioCurrentPos : number = 0;
bAudioPlayPro : number = 0;
nDuration : number = 0;
mSelectedShoudios : number = -1;
showRatingBanner : number = 0;
nRatingScore : number = 0;
nOldRatingScore : number = 0;
circleMarkRadius : number = 0;
nAppoveCount : number = 0;
hideImageContainer : number = 0;
minimize: number = 1;
hideAudio : number = 1;
rate:number = 1;
rating_count: number = 1;

audioFilePath : string = "";
audioFileDuration : string = "";
mPlayType : string = "initial";
RouteMediaPath : string = "";
RouteIndex : string = "";
RouteTitle : string = "";
mSelectedVideoFile : string = "";
strDeviceID : string = "";
description : string = "";
mSelectedVideoThumbnailFile : string = "";
mSelectedAudioFile : string = "";

createThumbnailOption : CreateThumbnailOptions ;
routePlayerFileTransfer :  FileTransferObject;

currentPosMark : L.Marker = null;

route_player_database : SQLiteObject = null;

allstats​ : any = [];
myZoom : any = {
    start:  0,
    end: 0
};

nPositionIntervalIndex : any = 0;
shoudiosCollectionData : any = [];
photoCollectionData : any = [];
mSelectedPhotoList : any = [];
notificationArray : any = [];
route_player_map: any = null;
currentPosCircle : any = null;
currentPos : any = null;
nIntervalId : any = null;
mCurrentPos : any = null;
CircleNumber : any ;
FinalTaget   : any ;
PositionMark : any ;
http_local_interval : any;
http_update_interval : any;
compassSubscription : any;
geolocationWatch : any = null;
batteryStatusSubcribe : any = null;
batteryLowSubcribe : any = null;
mLastLat : any = -1000;
mLastLng : any = -1000;
locationInterval : any = null;
mAndroidGPSInterval : any = null;
bgGeo : any;

bAudioFilePlay : boolean = false;
bFinishMessageShow : boolean = false;
bRouteEnd : boolean = false;
mOutFlag : boolean = false;
mAndroidAppPaused : boolean = false;
mAndroidNeedToStopGps : boolean = false;
audioFileLoaded : boolean = false;
bPaused : boolean = false;
bConfirmMessageShowing : boolean = false;

constructor(public navCtrl: NavController, public navParams: NavParams, private media: Media,
            private file : File, public sqlite : SQLite, public androidHttp : Http, public storage : Storage,
            public videoEditor : VideoEditor, public fileTransfer : FileTransfer, public platform : Platform,
            private alertCtrl: AlertController, public deviceOrientation : DeviceOrientation, public status : StatusBar,
            public localNotification : LocalNotifications, public iosHttp : HTTP, public iab : InAppBrowser,
            public badge : Badge, public toast : Toast) {
    this.audioFilePath = "";
    this.minimize = 1;

    this.nRouteID = this.navParams.get("collect_num");
    //this.status.hide();

    this.storage.get("uuid").then((result)=>{
        this.strDeviceID = result;
        this.preloadRemainData();

    }).catch((error)=>{});

    this.RouteMediaPath = this.file.dataDirectory + "data/" + this.nRouteID + "/media/";

    this.routePlayerFileTransfer = this.fileTransfer.create();

    this.AddLeafletCustomMarks();

}

ionViewDidEnter()
{
    this.platform.registerBackButtonAction(() =>
    {
        if(this.showRatingBanner == 1)
        {
            this.http_update_state();
            this.removeAllInterval();

            this.navCtrl.pop();
        }else
        {

            if(this.bRouteEnd == true)
            {
                this.showRatingBanner = 1;
            }else
            {
                this.http_update_state();
                this.removeAllInterval();
                this.navCtrl.pop();
            }
        }
    },1);
}

ionViewDidLeave()
{
    this.badge.clear();
}

removeAllInterval()
{
    if(this.batteryStatusSubcribe != null)
    {
        this.batteryStatusSubcribe.unsubscribe();

        this.batteryStatusSubcribe = null;
    }

    if(this.batteryLowSubcribe != null)
    {
        this.batteryLowSubcribe.unsubscribe();

        this.batteryLowSubcribe = null;
    }

    if(this.compassSubscription != null)
    {
        this.compassSubscription.unsubscribe();

        this.compassSubscription = null;
    }

    if(this.geolocationWatch != null)
    {
        this.geolocationWatch.unsubscribe();

        this.geolocationWatch = null;
    }

    clearInterval(this.http_local_interval);
    clearInterval(this.http_update_interval);
    clearInterval(this.locationInterval);

    this.pauseAudioFile();

    this.bgGeo.stop();

    this.localNotification.clearAll();
}
AddLeafletCustomMarks()
{
    this.CircleNumber = L.Icon.extend({
        options: {
        iconUrl: 'assets/routeicon.svg',
        number: '',
        shadowUrl: null,
        iconSize: new L.Point(69, 69),
            iconAnchor: new L.Point(34.5, 34.5),
            popupAnchor: new L.Point(0, 0),
            className: 'leaflet-circle-marker-icon'
        },

        createIcon: function () {
            var div = document.createElement('div');
            var img = this._createImg(this.options['iconUrl']);
            var numdiv = document.createElement('div');
            numdiv.setAttribute ( "class", "number" );
            numdiv.innerHTML = this.options['number'] || '';
            div.appendChild ( img );
            div.appendChild ( numdiv );
            this._setIconStyles(div, 'icon');
            return div;
        },

        createShadow: function () {
            return null;
        }
    });

    this.FinalTaget = L.Icon.extend({
        options: {
        iconUrl: 'assets/imgs/goal.png',
        shadowUrl: null,
        number: '',
        iconSize: new L.Point(44, 44),
            iconAnchor: new L.Point(22, 22),
            popupAnchor: new L.Point(0, 0),
            className: 'leaflet-goal-marker-icon'
        },

        createIcon: function () {
            var div = document.createElement('div');
            var img = this._createImg(this.options['iconUrl']);
            var numdiv = document.createElement('div');
            numdiv.setAttribute ( "class", "number-last" );
            numdiv.innerHTML = this.options['number'] || '';
            div.appendChild ( img );
            div.appendChild ( numdiv );
            img.setAttribute("style", "width:42px;height:42px;border:1px;box-shadow: 0px 0px 1px 1px #333333;");
            this._setIconStyles(div, 'icon');
            return div;
        },

        createShadow: function () {
            return null;
        }
    });

    this.PositionMark = L.Icon.extend({
        options: {
            iconUrl: 'assets/imgs/myicon.svg',
            number: '',
            shadowUrl: null,
            iconSize: new L.Point(28, 28),
            iconAnchor: new L.Point(14, 14),
            popupAnchor: new L.Point(0, 0),
            className: 'leaflet-position-marker-icon'
        },

        createIcon: function () {
            var div = document.createElement('div');
            var img = this._createImg(this.options['iconUrl']);
            img.style.width="28px";
            img.style.height="28px";
            img.id="current_mark";
            div.appendChild ( img );

            this._setIconStyles(div, 'icon');
            return div;
        },

        createShadow: function () {
            return null;
        }
    });
}
expand_view()
{
    this.minimize = 0;
}
titleMinimizePageChanged()
{
    let currentIndex = this.minimize_title.realIndex;

    var con = this;

    if(this.mSelectedShoudios == currentIndex)
        return;

    this.pauseAudioFile();

    this.showShoudios(currentIndex);

    this.centerTheMap(this.shoudiosCollectionData[currentIndex].lat, this.shoudiosCollectionData[currentIndex].lon);
}

ionViewDidLoad() {
    console.log('ionViewDidLoad RoutePlayerPage');
    this.loadPhotoGallery();

    this.platform.ready().then(_ => {

        var option = {
            timeout: 3000,
            enableHighAccuracy: true
        };

        var context = this;

        this.compassSubscription = this.deviceOrientation.watchHeading().subscribe(
            (data3: DeviceOrientationCompassHeading) => {

                if(this.currentPosMark != null && document.getElementById("current_mark") != undefined)
                {
                    document.getElementById("current_mark").style.transform = 'rotate(' + 0 + 'deg)';
                    document.getElementById("current_mark").style.transform = 'rotate(' + data3.trueHeading + 'deg)';
                }
            },(error: any) => {
                console.log(error+" - error message");

                if(error.code == 3)
                {
                    this.toast.show("Your device doesn't support orientation senor.", '3000', 'bottom').subscribe(
                        toast => {
                            console.log(toast);
                        }
                    );
                }
            });

        var context = this;

        this.bgGeo = (<any>window).BackgroundGeolocation;

        this.bgGeo.on('location', this.callbackFnf.bind(this), this.failureFnf.bind(this));
        this.bgGeo.ready({
            // Geolocation config
            reset:true,
            desiredAccuracy: this.bgGeo.DESIRED_ACCURACY_HIGH,
            distanceFilter: 10,
            stationaryRadius: 0,
            stopOnStationary:false,
            // Activity Recognition config
            locationUpdateInterval: 3000,
            activityRecognitionInterval: 10000,
            // Application config
            debug: true,  // <-- Debug sounds & notifications.
            startOnBoot: false,
            foregroundService: true,
            stopOnTerminate : false
            // HTTP / SQLite config
        }, function(state) {
            // This callback is executed when the plugin is ready to use.
            console.log("BackgroundGeolocation ready: ", state);
            if (!state.enabled) {
                context.bgGeo.start();
            }
        });
    });

    // this.locationInterval = setInterval(_=>{
    //      if(this.locationProvide.isTrackWorking() && this.locationProvide.lat != -1000)
    //      {
    //         this.storage.set("currentlat", this.locationProvide.lat);
    //         this.storage.set("currentlon", this.locationProvide.lng);
    //         this.mCurrentPos = new L.LatLng(this.locationProvide.lat, this.locationProvide.lng);
    //         this.currentPos = {lat:this.locationProvide.lat, lon:this.locationProvide.lng, rad : this.locationProvide.accur};

    //         this.updateMyLocCB(this.currentPos);
    //      }
    // }, 100);

    this.minimize_title.autoHeight=true;

    // this.http_local_interval = setInterval(_=>{
    //     if(this.shoudiosCollectionData.length == 0)
    //         return;

    //     var selectedItem = this.shoudiosCollectionData[this.mSelectedShoudios];

    //     if(this.currentPos != null)
    //         this.update_state(selectedItem.id, this.currentPos.lat, this.currentPos.lon);

    // }, 5000);

    // this.http_update_interval = setInterval(_=>{
    //     this.http_update_state();
    // }, 10000);
}

minimize_view()
{
    if(this.showRatingBanner == 1)
        return;

    if(this.minimize == 1)
    {
        this.minimize = 0;

        this.nAppoveCount ++;
        var selectedItem = this.shoudiosCollectionData[this.mSelectedShoudios];
    }else
    {
        this.minimize = 1;
    }
}

show_rounte_detail(selectedIndex)
{
    var selectedShoudios = this.shoudiosCollectionData[this.mSelectedShoudios];
    this.pauseAudioFile();
    this.navCtrl.push('route-detail-page', {"selectedShoudios":selectedShoudios, "selectedImage" : selectedIndex});
}

back()
{
    if(this.showRatingBanner == 1)
    {
        this.quitRoutine();
    }else
    {

        if(this.bRouteEnd == true)
        {
            this.showRatingBanner = 1;
        }else
        {
            this.quitRoutine();
        }
    }
}

quitRoutine()
{
    this.http_update_state();
    this.removeAllInterval();
    this.mOutFlag = true;
    this.navCtrl.pop();
}

callbackFnf(location) {
    var coords = location.coords;
    var lat    = coords.latitude;
    var lng    = coords.longitude;
    console.log('- Location: ', JSON.stringify(location));      

    console.log(location);
    this.storage.set("currentlat", lat);
    this.storage.set("currentlon", lng);
    this.mCurrentPos = new L.LatLng(lat, lng);
    this.currentPos = {lat:lat, lon:lng, rad : coords.accuracy};

    this.updateMyLocCB(this.currentPos);
}

failureFnf(errorCode) 
{
    console.warn('- BackgroundGeoLocation error: ', errorCode);
}

LoadShoudioList()
{
    this.shoudiosCollectionData = [];
    this.file.checkFile(this.file.dataDirectory , "data/" + this.nRouteID + "/" + "shoudios.json").then(_ => {
        this.androidHttp.get(this.file.dataDirectory + "data/" + this.nRouteID + "/collection.json").toPromise().then(collectionData => {
            var collectionJson = JSON.parse((<any>collectionData)._body);

            if(collectionJson != null)
            {
                this.mPlayType = collectionJson["playtype"];
            }
            var route = collectionJson["route"];
            var bFitBounds = false;
            if(route != null)
            {
                route = route.split('"').join("'");

                if(route.substring(0, 1) == "[" && route.substring(route.length - 1) == "]")
                {
                    route = route.substring(1, route.length - 1);

                    var latLonArray = route.split("','");

                    var resultArray : any = [];

                    for(let index = 0; index < latLonArray.length; index ++)
                    {
                        var perItem = latLonArray[index];

                        perItem = perItem.replace("'", "");

                        var perArray = perItem.split(",");

                        if(perArray.length == 2)
                        {
                            resultArray.push(new L.LatLng(parseFloat(perArray[0]), parseFloat(perArray[1])));
                        }

                        // if(index == latLonArray.length - 1)
                        // {
                        //     var marker = new L.Marker(new L.LatLng(parseFloat(perArray[0]), parseFloat(perArray[1])), {
                        //         icon:    new this.FinalTaget()
                        //     });

                        //     this.route_player_map.addLayer(marker);
                        //     marker.setZIndexOffset(0);
                        //     this.mLastLat = parseFloat(perArray[0]);
                        //     this.mLastLng = parseFloat(perArray[1]);
                        // }
                    }

                    if(resultArray.length != 0)
                    {

                        var polyLine = new L.Polyline(resultArray, {color:'#62bb46', weight:6, opacity:1, smoothFactor:1});

                        this.route_player_map.addLayer(polyLine);

                        var polyLine1 = new L.Polyline(resultArray, {color:'white', weight:4, opacity:1, smoothFactor:1});

                        this.route_player_map.addLayer(polyLine1);

                        this.route_player_map.fitBounds(polyLine.getBounds());

                        bFitBounds = true;
                    }
                }
            }

            this.androidHttp.get(this.file.dataDirectory + "data/" + this.nRouteID + "/" + "shoudios.json").toPromise().then(data =>
            {
                var shoudiosArray = JSON.parse((<any>data)._body);
                var tempArray = [];

                shoudiosArray.forEach(shoudiosArrayElement => {
                    tempArray.push(shoudiosArrayElement);
                });

                var markers = new L.MarkerClusterGroup();
                for(let h = 0; h < tempArray.length; h ++)
                {
                    var item = new Shoudios();

                    item.setData(tempArray[h]);
                    this.shoudiosCollectionData.push(item);
                    this.notificationArray.push(0);
                    var marker;
                    if(h != tempArray.length - 1)
                    {
                        marker = new L.Marker(new L.LatLng(parseFloat(item.lat), parseFloat(item.lon)), {
                            icon:   new this.CircleNumber({number: (h + 1)})
                        }).on('click', () => {
                            this.minimize_title.slideTo(h, 300);

                            this.minimize = 0;
                        });
                    }else
                    {
                        marker = new L.Marker(new L.LatLng(parseFloat(item.lat), parseFloat(item.lon)), {
                            icon:   new this.FinalTaget({number: (h + 1)})
                        }).on('click', () => {
                            this.minimize_title.slideTo(h, 300);
                            this.minimize = 0;
                        });

                    }
                    marker.setZIndexOffset(5000 + h);
                    this.route_player_map.addLayer(marker);
                }

                if(tempArray.length > 0)
                {
                    this.showShoudios(0);
                }

                if(bFitBounds == false)
                {
                    this.route_player_map.fitBounds(markers.getBounds());
                }
            });
        });

    }).catch(err => {
        //console.log(this.file.dataDirectory, "data/" + this.nRouteID + "/shoudios.json" + " does't exists");
    });
}

loadPhotoGallery()
{
    this.photoCollectionData = [];
    this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/photogallery.json").then(_ => {

        this.androidHttp.get(this.file.dataDirectory + "data/" + this.nRouteID + "/" + "photogallery.json").toPromise().then(data =>{
            var galleryArray = JSON.parse((<any>data)._body);

            galleryArray.forEach(element => {
                var item = new PhotoItem();

                item.setData(element);
                this.photoCollectionData.push(item);
            });

            this.loadmap();
        });
    }).catch(err => {
        this.loadmap();
    });
}

checkingStar(nMark)
{
    this.nOldRatingScore = this.nRatingScore;
    this.nRatingScore = nMark;
    if(this.nOldRatingScore != this.nRatingScore)
    {
        var strTitle = "Geef " + nMark + " sterren?";
        var strMessage = "Wil je deze route waarderen met " + nMark + " sterren?";

        this.bFinishMessageShow = true;

        var context = this;
        let alert = this.alertCtrl.create({
            title: strTitle,
            message: strMessage,
            buttons: [
                {
                    text: 'Change',
                    role: 'cancel',
                    handler: () => {
                        this.nRatingScore = this.nOldRatingScore;

                        context.bFinishMessageShow = true;
                    }
                },
                {
                    text: 'Yes',
                    handler: () => {
                        this.nRatingScore = nMark;

                        var platformType = "";

                        if(this.platform.is('ios'))
                        {
                            platformType = "i";
                        }

                        if(this.platform.is('android'))
                        {
                            platformType = "a";
                        }
                        var params = {
                            u:this.strDeviceID,
                            r: nMark,
                            i: this.nRouteID,
                            ai:'ivn',
                            au:28336,
                            t:'collection',
                            an:1,
                            de: platformType
                        };

                        this.iosHttp.post("https://shoudio.com/stats/rating_anon.php", params, {}).then((result)=>{}).catch((error)=>{});

                        this.quitRoutine();
                    }
                }
            ]
        });
        alert.present();
    }
}

realResourcePath(path : string)
{
    var result = path;

    if(result == null)
        return result;
    if(this.platform.is('ios'))
    {
        result = result.replace(/^file:\/\//, '');
    }

    return result;
}
showShoudios(index : number)
{
    if(index == undefined)
        return;

    clearInterval(this.nPositionIntervalIndex);
    this.mSelectedPhotoList = [];

    if(this.shoudiosCollectionData.length == 0)
        return;

    this.bPaused = false;
    this.bAudioPlayPro = 0;
    this.mSelectedShoudios = index;
    var selectedItem = this.shoudiosCollectionData[index];

    if(this.currentPos != null)
        this.update_state(selectedItem.id, this.currentPos.lat, this.currentPos.lon);

    this.description = selectedItem.description;
    this.RouteTitle = selectedItem.message;
    this.RouteIndex = "" + (index + 1);
    this.description = selectedItem.description;
    this.bPaused = false;
    this.bAudioPlayPro = 0;

    if(selectedItem.type == "shoudio")
    {
        this.mSelectedVideoFile = "";
    }
    document.getElementById("video_container").style.display = "none";
    if(selectedItem.type == "video")
    {
        var videoPath = this.file.dataDirectory + "data/" + this.nRouteID + "/media/vid_" + selectedItem.id + ".mp4";

        this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/media/img_" + selectedItem.id + ".jpg").then(()=>{
            this.mSelectedVideoFile = this.file.dataDirectory + "data/" + this.nRouteID + "/media/vid_" + selectedItem.id + ".mp4";
            this.mSelectedVideoThumbnailFile = this.realResourcePath(this.file.dataDirectory + "data/" + this.nRouteID + "/media/img_" + selectedItem.id + ".jpg");
            document.getElementById("video_container").style.display = "block";
            document.getElementById("video").style.backgroundImage = "url('" + this.mSelectedVideoThumbnailFile + "')";
            document.getElementById("video").style.backgroundSize = "cover";
            document.getElementById("video").style.backgroundPosition = "50% 50%";
        }).catch(()=>{
            this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/media/vid_" + selectedItem.id + ".mp4").then(()=>{

                this.createThumbnailOption = {fileUri:videoPath, outputFileName:"temp_thumbnail", atTime: 0, width:106, height:106, quality:100};

                this.videoEditor.createThumbnail(this.createThumbnailOption).then((resultPath)=>{

                    var cacheList = [
                        this.file.applicationDirectory,
                        this.file.applicationStorageDirectory,
                        this.file.dataDirectory,
                        this.file.cacheDirectory,
                        this.file.externalApplicationStorageDirectory,
                        this.file.externalDataDirectory,
                        this.file.externalCacheDirectory,
                        this.file.externalRootDirectory,
                        this.file.syncedDataDirectory,
                        this.file.documentsDirectory
                    ];

                    var tempList = [];

                    for(var i = 0; i < cacheList.length; i ++)
                    {
                        if(cacheList[i] == null || cacheList[i] == undefined)
                        {
                            continue;
                        }

                        tempList.push(cacheList[i]);
                    }

                    tempList.sort(function(a, b){
                        return a.length - b.length;
                    });

                    var tempFileUrl = resultPath;

                    tempFileUrl = "file://" + resultPath;

                    var mPath;
                    for(var i = 0; i < tempList.length; i ++)
                    {
                        if(tempFileUrl.indexOf(tempList[i]) != -1)
                        {
                            mPath = tempList[i];
                        }
                    }

                    this.file.copyFile(mPath, tempFileUrl.substring(mPath.length), this.file.dataDirectory, "data/" + this.nRouteID + "/media/img_" + selectedItem.id + ".jpg").then(()=>{

                        this.mSelectedVideoFile = this.file.dataDirectory + "data/" + this.nRouteID + "/media/vid_" + selectedItem.id + ".mp4";
                        this.mSelectedVideoThumbnailFile = this.realResourcePath(this.file.dataDirectory + "data/" + this.nRouteID + "/media/img_" + selectedItem.id + ".jpg");
                        document.getElementById("video_container").style.display = "block";
                        document.getElementById("video").style.backgroundImage = "url('" + this.mSelectedVideoThumbnailFile + "')";
                        document.getElementById("video").style.backgroundSize = "cover";
                        document.getElementById("video").style.backgroundPosition = "50% 50%";

                        this.file.removeFile(mPath, tempFileUrl.substring(mPath.length)).then(_=>{

                        }).catch(_=>{
                            //console.log('remove error');
                        });
                    }).catch((e)=>{
                        //console.log("Copy Error");
                        //console.log(e);
                    });

                }).catch(()=>{
                    //console.log("E't Ex" + videoPath);
                });

            }).catch(()=>{
                //console.log("Don't Ex" + videoPath);
            });
        });
    }

    if(selectedItem.type == "youtube")
    {
        var youtubeId = selectedItem.external_link;

        if(youtubeId == null || youtubeId == undefined)
        {
            this.mSelectedVideoThumbnailFile = "";
        }else
        {
            var externalThumbnailLink = "http://img.youtube.com/vi/" + youtubeId + "/default.jpg";
            this.mSelectedVideoFile = "";
            this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/youtubecache/"+ youtubeId + ".jpg").then(()=>{
                this.mSelectedVideoThumbnailFile = this.file.dataDirectory + "data/" + this.nRouteID + "/youtubecache/"+ youtubeId + ".jpg";
                document.getElementById("video_container").style.display = "block";

                this.mSelectedVideoFile = youtubeId;

                $("#video").css('background-image', "url('" + this.realResourcePath(this.mSelectedVideoThumbnailFile) + "')");
                $("#video").css('background-size', "cover");
                $("#video").css('background-position', "50% 50%");

            }).catch(()=>{

                this.routePlayerFileTransfer.download(externalThumbnailLink, this.file.dataDirectory + "data/" + this.nRouteID + "/youtubecache/"+ youtubeId + ".jpg").then((entry)=>{
                    this.mSelectedVideoThumbnailFile = this.file.dataDirectory + "data/" + this.nRouteID + "/youtubecache/"+ youtubeId + ".jpg";

                    this.mSelectedVideoFile = youtubeId;
                    document.getElementById("video_container").style.display = "block";

                    $("#video").css('background-image', "url('" + this.realResourcePath(this.mSelectedVideoThumbnailFile) + "')");
                    $("#video").css('background-size', "cover");
                    $("#video").css('background-position', "50% 50%");
                }).catch(()=>{
                    this.mSelectedVideoThumbnailFile = this.realResourcePath(this.file.dataDirectory + "data/" + this.nRouteID + "/youtubecache/"+ youtubeId + ".jpg");
                });
            });
        }
    }

    if(selectedItem.type == "text")
    {
        this.mSelectedVideoFile = "";
    }

    if(selectedItem.type == "image")
    {
        this.mSelectedVideoFile = "";
    }

    if(selectedItem.type == "poi")
    {
        this.mSelectedVideoFile = "";
    }

    if(parseInt(selectedItem.hasmp3) == 1)
    {
        this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/media/shoudio_" + selectedItem.id + ".mp3").then(()=>{
            this.audioFilePath = this.file.dataDirectory + "data/" + this.nRouteID + "/media/shoudio_" + selectedItem.id + ".mp3";

            this.loadAudioFile();
        }).catch(()=>{
            this.audioFilePath = "";

            this.hideAudioContainer();
        });
    }else
    {
        this.hideAudioContainer();
    }

    if(parseInt(selectedItem.hasimg) == 1)
    {
        this.hideImageContainer = 0;
        for(let i = 0; i < this.photoCollectionData.length; i ++)
        {
            if(this.photoCollectionData[i].shoudio_uid == selectedItem.shoudio_id)
            {
                this.file.checkFile(this.file.dataDirectory, "data/" + this.nRouteID + "/images/" + this.photoCollectionData[i].shoudio_uid + "_" + this.photoCollectionData[i].id + ".jpg").then(()=>{

                    var imageDirectory = this.file.dataDirectory + "data/" + this.nRouteID + "/images/" + this.photoCollectionData[i].shoudio_uid + "_" + this.photoCollectionData[i].id + ".jpg";
                    this.mSelectedPhotoList.push(imageDirectory);
                }).catch(()=>{
                    //console.log(this.file.dataDirectory + "data/" + this.nRouteID + "/images/" + this.photoCollectionData[i].shoudio_uid + "_" + this.photoCollectionData[i].id + ".jpg");
                });
            }
        }
    }else
    {
        if(selectedItem.type == "video" || selectedItem.type == "youtube")
        {
            this.hideImageContainer = 0;
        }else
        {
            this.hideImageContainer = 1;
        }
    }

    var context = this;

    if(this.platform.is('ios') || this.platform.is('android'))
    {
        $(document).on('click', 'a[href^="http"]', function (e) {
            var url = $(this).attr('href');
            context.iab.create(url, '_system', 'closebuttoncaption=Done');

            e.preventDefault();
        });
    }

}
showVideo()
{
    if(this.mSelectedVideoFile == "")
        return;

    if(this.mSelectedVideoThumbnailFile.indexOf("youtubecache") > -1)
    {
        //this.navCtrl.push('youtube-video-player-page', {"videopath" : this.mSelectedVideoFile});
        this.pauseAudioFile();

        return;
    }

   if(this.platform.is('android') || this.platform.is('ios'))
    {
        //this.androidplayer.show({url: this.mSelectedVideoFile});

        var selectedItem = this.shoudiosCollectionData[parseInt(this.RouteIndex) - 1];

        var posterPath = this.file.dataDirectory + "data/" + this.nRouteID + "/media/testimg_" + selectedItem.id + ".jpg";
        this.pauseAudioFile();
        this.navCtrl.push('video-player-page', {"videopath" : this.mSelectedVideoFile, "poster" : posterPath, "routeId" : this.nRouteID, "shoudiosId" : selectedItem.id});

    }
}
drawPolygonPath()
{
    if(this.nRouteID == null || this.nRouteID == undefined)
        return;

    this.androidHttp.get(this.file.dataDirectory + "data/" + this.nRouteID + "/collection.json").toPromise().then(datas => {
        var collectionJson = JSON.parse((<any>datas)._body);

        var route = collectionJson["route"];

        if(route != null)
        {
            route = route.split('"').join("'");

            if(route.substring(0, 1) == "[" && route.substring(route.length - 1) == "]")
            {
                route = route.substring(1, route.length - 1);

                var latLonArray = route.split("','");

                var resultArray : any = [];

                for(let index = 0; index < latLonArray.length; index ++)
                {
                    var perItem = latLonArray[index];

                    perItem = perItem.replace("'", "");

                    var perArray = perItem.split(",");

                    if(perArray.length == 2)
                    {
                        resultArray.push(new L.LatLng(parseFloat(perArray[0]), parseFloat(perArray[1])));
                    }
                }

                if(resultArray.length != 0)
                {

                    var polyLine = new L.Polyline(resultArray, {color:'white', weight:5, opacity:1, smoothFactor:1});

                    this.route_player_map.addLayer(polyLine);

                    var polyLine1 = new L.Polyline(resultArray, {color:'green', weight:2, opacity:1, smoothFactor:1});

                    this.route_player_map.addLayer(polyLine1);

                    this.route_player_map.fitBounds(polyLine.getBounds());
                }
            }
        }

    });
}
loadmap()
{
    this.route_player_map = L.map("route_player_map").fitWorld();

    var url = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';

    var onlineLayer_base = L.tileLayer(url, {
        attribution: '&copy; OpenStreetMap',
        subdomains: 'abc',
        maxZoom: 20
    }).addTo(this.route_player_map);

    L.tileLayer(this.realResourcePath(this.file.dataDirectory + "data/" + this.nRouteID + '/{z}/{x}/{y}.png'), {
        attributions: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
        detectRetina:false
    }).addTo(this.route_player_map);

    //this.drawPolygonPath();
    this.LoadShoudioList();
}

loadAudioFile()
{
    var fileName = this.get_file_name(this.audioFilePath);

    if(!this.platform.is("ios"))
    {
        if(this.audioFile != null)
        {
            this.audioFile.release();

            this.audioFile = null;
        }
    }

    if(fileName == "")
    {
        this.hideAudioContainer();
    }else
    {

        if(this.platform.is("ios"))
        {
            this.audioFile = this.media.create(this.file.dataDirectory.replace(/^file:\/\//, '') + "data/" + this.nRouteID + "/media/" + fileName);
        }else
        {
            if(this.audioFile != null)
            {
                this.audioFile.release();

                this.audioFile = null;
            }

            this.audioFile = this.media.create(this.file.dataDirectory + "data/" + this.nRouteID + "/media/" + fileName);
        }

        //console.log(this.file.dataDirectory + "data/" + this.nRouteID + "/media/" + fileName);
        this.audioFile.play();
        this.audioFile.setVolume(0.0);
        this.nDuration = -1;

        this.audioFile.onStatusUpdate.subscribe(status => {
            if(status.toString() == "4")
            {
                this.bPaused = false;
            }
        });

        var self = this;
        var interval = setInterval(function(){
            if(self.nDuration == -1 || self.nDuration === undefined)
            {
                self.nDuration = self.audioFile.getDuration();
            }else
            {

                self.audioFile.pause();
                self.audioFile.seekTo(0);
                self.bAudioPlayPro = 0;
                self.audioFile.setVolume(1.0);
                clearInterval(interval);
            }
        }, 100);

        this.audioCurrentPos = 0;
        this.audioFileLoaded = true;
        this.audioFileDuration = "00:00:00";

        this.showAudioContainer();
    }
}

hideAudioContainer()
{
    this.hideAudio = 1;

    if(!this.platform.is("ios"))
    {
        if(this.audioFile != null)
        {
            this.audioFile.release();

            this.audioFile = null;
        }
    }
}

showAudioContainer()
{
    this.hideAudio = 0;
}

startCurrentPos()
{
    this.nPositionIntervalIndex = setInterval(() =>{
        this.audioFile.getCurrentPosition().then((position) => {
            if($(".progress-outer").width() - $(".progress-inner").width() < 10)
            {
                var nDifference = $(".progress-outer").width() - $(".progress-inner").width();

                $(".progress-inner").css('border-bottom-left-radius', '10px');
                $(".progress-inner").css('border-top-left-radius', '10px');
                $(".progress-inner").css('border-bottom-right-radius', nDifference + 'px');
                $(".progress-inner").css('border-top-right-radius', nDifference + 'px');
            }else
            {
                $(".progress-inner").css('border-bottom-left-radius', '10px');
                $(".progress-inner").css('border-top-left-radius', '10px');
                $(".progress-inner").css('border-bottom-right-radius', '0px');
                $(".progress-inner").css('border-top-right-radius', '0px');
            }
            this.bAudioPlayPro = parseInt(position) * 100/ this.nDuration;

            this.audioFileDuration = this.makeDurationTypeMinute(parseInt(parseInt(position).toFixed(0)));

            if(parseInt(position).toFixed(0) == this.nDuration.toFixed(0))
            {
                clearInterval(this.nPositionIntervalIndex);
                this.bAudioPlayPro = 0;
                this.audioFile.seekTo(0);
                this.audioFileDuration = "00:00:00";
                this.pauseAudioFile();
            }
        });
    }, 300);
}

makeDurationTypeMinute(duration : number)
{
    if(duration == -1)
    {
        return "00:00:00";
    }else
    {
        var nHour = Math.floor(duration / 60 /60);
        var nMinute = Math.floor(duration / 60);
        var nSecond = duration % 60;

        var strHour =  nHour < 10 ? "0" + nHour : nHour;
        var strMinute =  nMinute < 10 ? "0" + nMinute : nMinute;
        var strSecond =  nSecond < 10 ? "0" + nSecond : nSecond;

        return strHour + ":" + strMinute + ":" + strSecond;
    }
}

pauseAudioFile()
{
    if(this.audioFileLoaded == false)
        return;

    clearInterval(this.nPositionIntervalIndex);

    if(this.bPaused == true)
    {
        this.audioFile.pause();
        this.bPaused = false;
    }
}

playAudioFile()
{
    if(this.audioFileLoaded == false)
        return;

    this.startCurrentPos();
    if(this.bPaused == true)
    {
        this.audioFile.play();
        this.bPaused = false;
    }else
    {
        this.bPaused = true;
        this.audioFile.seekTo(0);
        this.audioFile.play();
    }
}

resumeAudioFile()
{

}

get_file_name(url)
{
    if(url === undefined)
    {
        return "";
    }

    var startIndex = (url.indexOf('\\') >= 0 ? url.lastIndexOf('\\') : url.lastIndexOf('/'));
    var filename = url.substring(startIndex);
    if (filename.indexOf('\\') === 0 || filename.indexOf('/') === 0)
    {
        filename = filename.substring(1);
    }

    var nPos = filename.indexOf("?");

    if(nPos == -1)
    {
        return filename;
    }

    return filename.substring(0, nPos);
}

updateMyLocCB(e)
{
    var lat = e.lat;
    var lon = e.lon;
    var rad = e.rad;
    var newLatLng = new L.LatLng(lat, lon);

    if(this.route_player_map != null)
    {
        if(this.currentPosCircle == null || this.currentPosCircle == undefined)
        {
            this.currentPosCircle = L.circle(newLatLng, e.rad, {color: '#EEEEEE',stroke:false, fillColor: '#EEEEEE'});

            this.currentPosCircle.addTo(this.route_player_map);
            //this.route_player_map.addLayer(this.currentPosCircle);
            this.circleMarkRadius = e.rad;

            this.currentPosCircle.setRadius(e.rad);
        }

        if(this.currentPosMark == null || this.currentPosMark == undefined)
        {
            this.currentPosMark = new L.Marker(newLatLng, {icon:new this.PositionMark()});
            this.route_player_map.addLayer(this.currentPosMark);
        }

        if(this.currentPosCircle != null)
        {
            this.currentPosCircle.setLatLng(newLatLng);
            this.circleMarkRadius = e.rad;
            this.currentPosCircle.setRadius(e.rad);

            if(e.rad < 5)
            {
                this.currentPosCircle.setStyle({fillOpacity:0});
            } else
            {
                this.currentPosCircle.setStyle({fillOpacity:0.3});
            }
        }

        if(this.currentPosMark != null)
        {
            this.currentPosMark.setLatLng(newLatLng);
            this.currentPosMark.setZIndexOffset(999999999);
        }
    }

    if(this.shoudiosCollectionData.length > 0)
    {
        var currentShoudiosItem = this.shoudiosCollectionData[this.mSelectedShoudios];
        var currentShoudiosDistance = 25;

        if(currentShoudiosItem != null && currentShoudiosItem != undefined)
        {
            if(currentShoudiosItem.beacon_distance != null && currentShoudiosItem.beacon_distance != undefined && currentShoudiosItem.beacon_distance != "")
            {
                currentShoudiosDistance = parseFloat(currentShoudiosItem.beacon_distance);
            }

            if(this.route_player_result_calc_dist(lat, lon, currentShoudiosItem.lat, currentShoudiosItem.lon) < currentShoudiosDistance)
            {
                if(this.notificationArray[this.mSelectedShoudios] == 0 && rad <= 25)
                {
                    this.localNotification.schedule({
                        text: currentShoudiosItem.message,
                    });

                    this.notificationArray[this.mSelectedShoudios] = 1;

                    this.minimize = 0;
                }

                if(this.mSelectedShoudios == this.shoudiosCollectionData.length - 1)
                {
                    if(this.bRouteEnd == false)
                    {
                        this.bRouteEnd = true;

                        return;
                    }
                }

                return;
            }
        }

        if(this.mPlayType == "initial")
        {

        }else
        {
            if(this.mPlayType == "sequential" || this.mPlayType == "" || this.mPlayType == null || this.mPlayType == undefined)
            {
                var shoudiosItem = this.shoudiosCollectionData[this.mSelectedShoudios + 1];

                var distance = 25;

                if(shoudiosItem != null && shoudiosItem != undefined)
                {
                    if(shoudiosItem.beacon_distance != null && shoudiosItem.beacon_distance != undefined && shoudiosItem.beacon_distance != "")
                    {
                        distance = parseFloat(shoudiosItem.beacon_distance);
                    }

                    if(this.route_player_result_calc_dist(lat, lon, shoudiosItem.lat, shoudiosItem.lon) < distance)
                    {
                        if(this.notificationArray[this.mSelectedShoudios + 1] == 0 && rad <= 25)
                        {
                            this.localNotification.schedule({
                                text: shoudiosItem.message,
                            });

                            this.notificationArray[this.mSelectedShoudios + 1] = 1;

                            this.minimize = 0;

                            this.minimize_title.slideTo(this.mSelectedShoudios + 1);
                        }

                        if(this.mSelectedShoudios + 1 == this.shoudiosCollectionData.length - 1)
                        {
                            if(this.bRouteEnd == false)
                            {
                                this.bRouteEnd = true;
                            }
                        }
                    }
                }

            }else
            {
                for(let k = 0; k < this.shoudiosCollectionData.length; k ++)
                {
                    var shoudiosItem = this.shoudiosCollectionData[k];
                    var distance = 25;

                    if(shoudiosItem.beacon_distance != null && shoudiosItem.beacon_distance != undefined && shoudiosItem.beacon_distance != "")
                    {
                        distance = parseFloat(shoudiosItem.beacon_distance);
                    }
                    if(this.route_player_result_calc_dist(lat, lon, shoudiosItem.lat, shoudiosItem.lon) < distance)
                    {
                        if(this.notificationArray[k] == 0 && rad <= 25)
                        {
                            this.localNotification.schedule({
                                text: shoudiosItem.message,
                            });

                            this.notificationArray[k] = 1;

                            this.minimize = 0;

                            this.minimize_title.slideTo(k);

                        }

                        if(k == this.shoudiosCollectionData.length - 1)
                        {
                            if(this.bRouteEnd == false)
                            {
                                this.bRouteEnd = true;
                            }
                        }
                    }
                }
            }
        }
    }

}

route_player_result_calc_dist(lat1, lon1, lat2, lon2) {
    var R  = 6376.136; // km
    var dLat  = (lat2-lat1) * Math.PI / 180;
    var dLon = (lon2-lon1) * Math.PI / 180;
    var lat1 : any = lat1 * Math.PI / 180;
    var lat2 : any = lat2 * Math.PI / 180;
    var a : any = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
    var c : any = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var distance:any = R * c * 1000;

    return distance;
}

update_state(shoudios_id, lat, lon)
{
    var d = new Date();
    var n = d.getTime();

    var strStateQuery = "INSERT INTO stats (id, shoudioid, collections_id, created_on, lat, lon) SELECT MAX( id ) + 1, " + shoudios_id + ", " + this.nRouteID + ", '" + n + "', " + lat + ", " + lon + " FROM stats";

    if(this.route_player_database == null)
    {
        this.sqlite.create({
            name: 'place.db',
            location: 'default'
        }).then((db: SQLiteObject) => {
            this.route_player_database = db;
            this.route_player_database.executeSql(strStateQuery, []).catch((error)=>{
                //console.log("Error" + strStateQuery);
            });

            this.allstats​.push('of:'+shoudios_id+':0:'+this.nRouteID +':'+this.strDeviceID+':'+lat +':'+lon+':'+ parseInt((n / 1000) + "" ));
        });
    }else
    {
        this.route_player_database.executeSql(strStateQuery, []).catch((error)=>{
            //console.log("Error" + strStateQuery);
        });

        this.allstats​.push('of:'+shoudios_id+':0:' + this.nRouteID +':'+this.strDeviceID+':'+lat +':'+lon+':' + parseInt((n / 1000) + "" ));
    }
}

preloadRemainData()
{
    this.sqlite.create({
        name: 'place.db',
        location: 'default'
    }).then((db: SQLiteObject) => {
        var strQuery = "select * from stats";

        db.executeSql(strQuery, []).then((searchResult) =>{
            if(searchResult.rows.length > 0)
            {
                for(var i = 0; i < searchResult.rows.length; i ++)
                {
                    //console.log(searchResult.rows.item(i).created_on);
                    this.allstats​.push('of:'+searchResult.rows.item(i).shoudioid+':0:'+searchResult.rows.item(i).collections_id+':'+this.strDeviceID+':'+searchResult.rows.item(i).lat +':'+searchResult.rows.item(i).lon+':'+ parseInt((parseInt(searchResult.rows.item(i).created_on) / 1000) + ""));
                }

                var platformType = "";
                if(this.platform.is('ios'))
                {
                    platformType = "i";
                }

                if(this.platform.is('android'))
                {
                    platformType = "a";
                }
            }
        })

    });
}

http_update_state()
{
    var platformType = "";
    if(this.platform.is('ios'))
    {
        platformType = "i";
    }

    if(this.platform.is('android'))
    {
        platformType = "a";
    }

    if(this.allstats.length == 0)
        return;

    var param = {t:JSON.stringify(​this.allstats​),u:this.strDeviceID,an:1,ai:'ivn', au:28336,de:platformType};

    this.iosHttp.post("https://shoudio.com/stats/bulk.php", param, {}).then((result)=>{
        var jsonArray = JSON.parse((<any>result).data);

        if(parseInt(jsonArray.statuscode) == 200)
        {
            var strQuery = "delete from stats where id <> 0";

            this.route_player_database.executeSql(strQuery, []);
            this.allstats = [];
        }

    }).catch((error)=>{
        //console.log(error);
    });

}

centerTheMap(lati,loni) {
    this.route_player_map.panTo(new L.LatLng(lati,loni));
}

centerMapCB(e) {
    this.centerTheMap(e.lat,e.lon);
};

}

AlexTerry1024 commented 6 years ago

Please check this code, what is wrong?

christocracy commented 6 years ago

I'm not going to look at all that code. It has nothing to do with the SampleApp.

christocracy commented 6 years ago

This issue is titled "It shows only two log". I don't even know what you're asking.

AlexTerry1024 commented 6 years ago

I mean it only call callbackFnf twice.

christocracy commented 6 years ago

What has your code got to do with the SampleApp?

AlexTerry1024 commented 6 years ago

this.bgGeo.on('location', this.callbackFnf.bind(this), this.failureFnf.bind(this)); this.bgGeo.ready({ // Geolocation config reset:true, desiredAccuracy: this.bgGeo.DESIRED_ACCURACY_HIGH, distanceFilter: 10, stationaryRadius: 0, stopOnStationary:false, // Activity Recognition config locationUpdateInterval: 3000, activityRecognitionInterval: 10000, // Application config debug: true, // <-- Debug sounds & notifications. startOnBoot: false, foregroundService: true, stopOnTerminate : false // HTTP / SQLite config }, function(state) { // This callback is executed when the plugin is ready to use. console.log("BackgroundGeolocation ready: ", state); if (!state.enabled) { context.bgGeo.start(); } });

christocracy commented 6 years ago

Your code has nothing to do with the SampleApp. That is your own custom code. I don't support your own custom code here at the SampleApp.

If you're having problem with implementing the plugin in your own app, this is the wrong place to post support requests.

Go post an issue at the plugin repo itself. https://github.com/transistorsoft/cordova-background-geolocation-lt