Get MP3 ID3 Metadata from remote URLS

Posted on

Firstly, I didn’t create this, I’ve just making it easy to understand with a full example.

You can read more of it here, but only because of archive.org.

To begin, download this library from here: http://getid3.sourceforge.net/

when you open the zip folder, you’ll see ‘getid3’. Save that folder in to your working folder.

Next, create a folder called “temp” in that working folder that the following script is going to be running from.

Basically, what it does is download the first 64k of the file, and then read the metadata from the file.

I enjoy a simple example. I hope this helps.


<?php

require_once("getid3/getid3.php");

$url_media = "http://domain.com/myfile.mp3"

$a=getfileinfo($url_media);

echo"<pre>";

echo $a['tags']['id3v2']['album'][0] . "\n";  
echo $a['tags']['id3v2']['artist'][0] . "\n";  
echo $a['tags']['id3v2']['title'][0] . "\n";  
echo $a['tags']['id3v2']['year'][0] . "\n"; 
echo $a['tags']['id3v2']['year'][0] . "\n";  

echo "\n-----------------\n";

//print_r($a['tags']['id3v2']['album']);

echo "-----------------\n";

//print_r($a);

echo"</pre>";

function getfileinfo($remoteFile)

{

$url=$remoteFile;
$uuid=uniqid("designaeon_", true);
$file="temp/".$uuid.".mp3";
$size=0;
$ch = curl_init($remoteFile);
//==============================Get Size==========================//
$contentLength = 'unknown';
$ch1 = curl_init($remoteFile);
curl_setopt($ch1, CURLOPT_NOBODY, true);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_HEADER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, true); //not necessary unless the file redirects (like the PHP example we're using here)
$data = curl_exec($ch1);
curl_close($ch1);
if (preg_match('/Content-Length: (\d+)/', $data, $matches)) {
$contentLength = (int)$matches[1];
$size=$contentLength;
}
//==============================Get Size==========================//


if (!$fp = fopen($file, "wb")) {
echo 'Error opening temp file for binary writing';
return false;
} else if (!$urlp = fopen($url, "r")) {
echo 'Error opening URL for reading';
return false;
}
try {
$to_get = 65536; // 64 KB
$chunk_size = 4096; // Haven't bothered to tune this, maybe other values would work better??
$got = 0; $data = null;

// Grab the first 64 KB of the file
while(!feof($urlp) && $got < $to_get) { $data = $data . fgets($urlp, $chunk_size); $got += $chunk_size; } fwrite($fp, $data); // Grab the last 64 KB of the file, if we know how big it is. 
if ($size > 0) {
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RESUME_FROM, $size - $to_get);
curl_exec($ch);
}

// Now $fp should be the first and last 64KB of the file!!

@fclose($fp);
@fclose($urlp);
} 
catch (Exception $e) {
@fclose($fp);
@fclose($urlp);
echo 'Error transfering file using fopen and cURL !!';
return false;
}

$getID3 = new getID3;
$filename=$file;
$ThisFileInfo = $getID3->analyze($filename);
getid3_lib::CopyTagsToComments($ThisFileInfo);
unlink($file);
return $ThisFileInfo;
}

?>

RGB Lights for the MAC

Posted on Updated on

I have bought this for 3 bucks.

https://www.ebay.com.au/itm/282231990280

I’ll be combining the knowledge from this post:

https://www.instructables.com/id/USB-NeoPixel-Deco-Lights-via-Digispark-ATtiny85/

And this video:

 

And will look at getting some RGB lights

https://www.ebay.com.au/itm/5V-LED-Strip-WS2812B-5050-RGB-30-60-144LEDs-M-ws2812-IC-Individual-Addressable/253054192813?var=552124369523

And this
https://www.ebay.com.au/itm/324032880391

As well as some joiners.

https://www.ebay.com.au/itm/5Pcs-3-pin-connectors-PCB-Solderless-for-WS2811-WS2812B-SK6812-led-pixel-strip/112087601742?hash=item1a18f1124e:g:Xs0AAOSwMtxXqWWg

This could be a bit of fun to brighten up my desk set up. ūüėÄ

I plan on putting these lights behind the screens, and under the desk glass to create ambient lighting, that I can change the colour of, using the computer. Should be pretty sweet.

Now to wait 2 months for them in the post…

UPDATE:
It’s now the 28th of May, and all of the final bits have arrived. In this process, I’ve already lost the cable connectors, so I’ll look in to either getting new ones or ripping apart the office… But, testing will happen soon.

IONIC Build Errors with solutions

Posted on Updated on

Hi friends,

As I’m working on different apps, on multiple platforms and things, I thought I’d start a list of some of the errors I’d been getting, and how I solved them in IONIC.

Some of these solutions may help you. Most of these are for v3 of IONIC. Other settings vary.

I’m sure I’ll keep adding to this.

It’s a very messy file, but if Google brings you here, I hope it will help you.

 


Failed to install ‘cordova-sqlite-storage’: CordovaError: Using “requireCordovaModule” to load non-cordova module “q” is not supported.
https://github.com/xpbrew/cordova-sqlite-storage/issues/856#issuecomment-497298630

Cordova error: Using ‚ÄúrequireCordovaModule‚ÄĚ to load non-cordova module ‚Äúq‚ÄĚ is not supported
https://stackoverflow.com/a/55321875/1190051


https://github.com/crosswalk-project/cordova-plugin-crosswalk-webview/issues/205#issuecomment-405052996

simply add this
cordova plugin add cordova-android-support-gradle-release –variable ANDROID_SUPPORT_VERSION=27.+
and run/build again.


ERROR ITMS-90174: “Missing Provisioning Profile – Apps must contain a provisioning profile in a file named embedded.mobileprovision.”
https://stackoverflow.com/a/52654888/1190051


> cordova build ios –release
CordovaError: Promise rejected with non-error: ‘ios-deploy was not found. Please download, build and install version 1.9.2 or greater from https://github.com/ios-control/ios-deploy into your path, or do \’npm install -g ios-deploy\”
at cli.catch.err (/Users/stephenmonro/ionicApps/C4I International/node_modules/cordova/bin/cordova:29:15)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ERROR] An error occurred while running subprocess cordova.

cordova build ios –release exited with exit code 1.

Re-running this command with the –verbose flag may provide more information.
Analyzing dependencies
Downloading dependencies
Generating Pods project
Integrating client project
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
Updating spec repo `master`
$ /usr/bin/git -C /Users/stephenmonro/.cocoapods/repos/master fetch origin –progress
remote: Enumerating objects: 1441, done.
remote: Counting objects: 100% (1441/1441), done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 2771 (delta 1275), reused 1191 (delta 1191), pack-reused 1330
Receiving objects: 100% (2771/2771), 320.66 KiB | 767.00 KiB/s, done.
Resolving deltas: 100% (1828/1828), completed with 553 local objects.
From https://github.com/CocoaPods/Specs
5bdc3da58dc..70702dce5ff master -> origin/master
$ /usr/bin/git -C /Users/stephenmonro/.cocoapods/repos/master rev-parse –abbrev-ref HEAD
master
$ /usr/bin/git -C /Users/stephenmonro/.cocoapods/repos/master reset –hard origin/master
HEAD is now at 70702dce5ff [Add] TidySplits 1.0.4
Updating spec repo `trunk`

CocoaPods 1.9.0.beta.3 is available.
To update use: `sudo gem install cocoapods –pre`
[!] This is a test version we’d love you to try.

For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.9.0.beta.3

The file /Users/stephenmonro/ionicApps/C4I International/platforms/ios/Christians for Israel.xcworkspace does not exist.
Problem solved here: unplug the ipad, or the device.
https://github.com/ios-control/ios-deploy/issues/332#issuecomment-552854357

Solution:

I experience this error if my phone is connected to my computer (via cable) when I am running the build command.

Simply unplugging the cable solved the problem.

 


npm update


ERROR:
[app-scripts] fs.js:114
[app-scripts] throw err;
[app-scripts] ^
[app-scripts] Error: ENOENT: no such file or directory, scandir ‘/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/node-sass/vendor’
[app-scripts] at Object.readdirSync (fs.js:785:3)

SOURCE:
https://github.com/sass/node-sass/issues/1579#issuecomment-452181858

FIX:
node ./node_modules/node-sass/scripts/install.js


ERRORS:

stephenmonro@SMMMacPro:~/ionicApps/wpimportsqlite$ ionic serve
> ionic-app-scripts serve –address localhost –port 8101 –livereload-port 35730 –dev-logger-port 53704 –nobrowser
[app-scripts] [23:24:14] ionic-app-scripts 3.2.4
[app-scripts] [23:24:14] watch started …
[app-scripts] [23:24:14] build dev started …
[app-scripts] [23:24:14] Proxy added:/wp-json => https://www.c4israel.org/wp-json
[app-scripts] [23:24:14] Proxy added:/resources/app/pdf => https://www.c4israel.com.au/resources/app/pdf/
[app-scripts] [23:24:14] clean started …
[app-scripts] [23:24:14] clean finished in 2 ms
[app-scripts] [23:24:14] copy started …
[app-scripts] [23:24:14] deeplinks started …
[app-scripts] [23:24:15] deeplinks finished in 336 ms
[app-scripts] [23:24:15] transpile started …
[app-scripts] [23:24:22] typescript: node_modules/@types/node/events.d.ts, line: 21
[app-scripts] ‘=’ expected.
[app-scripts] L20: function on(emitter: EventEmitter, event: string): AsyncIterableIterator<any>;
[app-scripts] L21: const captureRejectionSymbol: unique symbol;
[app-scripts] ‘=’ expected.
[app-scripts] [23:24:22] typescript: node_modules/@types/node/events.d.ts, line: 32
[app-scripts] L32: const errorMonitor: unique symbol;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 361
[app-scripts] ‘=’ expected.
[app-scripts] L361: const REPL_MODE_SLOPPY: unique symbol;
[app-scripts] ‘=’ expected.
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 367
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 26
[app-scripts] L367: const REPL_MODE_STRICT: unique symbol;
[app-scripts] ‘=’ expected.
[app-scripts] L25: let replDefaults: InspectOptions;
[app-scripts] L26: const custom: unique symbol;
[app-scripts] ‘=’ expected.
[app-scripts] L120: namespace promisify {
[app-scripts] L121: const custom: unique symbol;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 121
[app-scripts] [23:24:23] typescript: node_modules/@types/node/events.d.ts, line: 21
[app-scripts] Cannot find name ‘unique’.
[app-scripts] L20: function on(emitter: EventEmitter, event: string): AsyncIterableIterator<any>;
[app-scripts] L21: const captureRejectionSymbol: unique symbol;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/events.d.ts, line: 21
[app-scripts] Cannot find name ‘symbol’. Did you mean ‘Symbol’?
[app-scripts] L20: function on(emitter: EventEmitter, event: string): AsyncIterableIterator<any>;
[app-scripts] L21: const captureRejectionSymbol: unique symbol;
[app-scripts] Cannot find name ‘unique’.
[app-scripts] [23:24:23] typescript: node_modules/@types/node/events.d.ts, line: 32
[app-scripts] L32: const errorMonitor: unique symbol;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/events.d.ts, line: 32
[app-scripts] Cannot find name ‘symbol’. Did you mean ‘Symbol’?
[app-scripts] L32: const errorMonitor: unique symbol;
[app-scripts] Cannot find name ‘unique’.
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 361
[app-scripts] L361: const REPL_MODE_SLOPPY: unique symbol;
[app-scripts] Cannot find name ‘symbol’. Did you mean ‘Symbol’?
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 361
[app-scripts] L361: const REPL_MODE_SLOPPY: unique symbol;
[app-scripts] Cannot find name ‘unique’.
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 367
[app-scripts] [23:24:23] typescript: node_modules/@types/node/repl.d.ts, line: 367
[app-scripts] L367: const REPL_MODE_STRICT: unique symbol;
[app-scripts] Cannot find name ‘symbol’. Did you mean ‘Symbol’?
[app-scripts] L367: const REPL_MODE_STRICT: unique symbol;
[app-scripts] Cannot find name ‘unique’.
[app-scripts] L25: let replDefaults: InspectOptions;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 26
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 26
[app-scripts] L26: const custom: unique symbol;
[app-scripts] Cannot find name ‘symbol’. Did you mean ‘isSymbol’?
[app-scripts] L25: let replDefaults: InspectOptions;
[app-scripts] L26: const custom: unique symbol;
[app-scripts] Cannot find name ‘unique’.
[app-scripts] L120: namespace promisify {
[app-scripts] L121: const custom: unique symbol;
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 121
[app-scripts] [23:24:23] typescript: node_modules/@types/node/util.d.ts, line: 121
[app-scripts] Cannot find name ‘symbol’.
[app-scripts] L120: namespace promisify {
[app-scripts] L121: const custom: unique symbol;

[INFO] Development server running!

Local: http://localhost:8101

Use Ctrl+C to quit this process

[INFO] Browser window opened to http://localhost:8101!

[app-scripts] [23:24:23] watch ready in 8.56 s
[app-scripts] [23:24:23] copy finished in 8.53 s

SOURCE:
https://forum.ionicframework.com/t/typescript-error-expected-and-more/181140/10?u=stephenmonro
FIX:
npm install typescript@2.7.2


Error:

[23:51:47] typescript error
Cannot find type definition file for ‘@types’.

[23:51:47] ionic-app-script task: “build”
[23:51:47] Error: Failed to transpile TypeScript
Error: Failed to transpile TypeScript
at errorCheckProgram (/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:119:39)
at Object.<anonymous> (/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:89:21)
at step (/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:32:23)
at Object.next (/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:13:53)
at fulfilled (/Users/stephenmonro/ionicApps/wpimportsqlite/node_modules/@ionic/app-scripts/dist/aot/aot-compiler.js:4:58)
[ERROR] An error occurred while running subprocess ionic-app-scripts.

LINK:
https://github.com/ionic-team/ionic-app-scripts/issues/1529#issuecomment-496652630

SOLUTION:
What seems to fix it is to add
“types”: []
to the
tsconfig.json’s compilerOptions.


 

High Sierra Security Update Jan 2020 Problem

Posted on Updated on

Today, I followed the update procedure of Apple to update to the latest MacOS Security updates. And… it didn’t go so well…

I tried the old PRAM reset and also an SMC reset as well. It still didn’t work. I got in to the recovery part as well, and was able to do a first aid on the disk. It all checked out well.

I also tried Safe Mode, but that didn’t really work properly, but it did spit out a lot of good information. I spotted something along lines of it hanging on a KEXT or similar.

Nothing really worked and it just stayed on this window, it basically looks like it’s hung…

After a few hours, nothing.

So I went to an Apple store, and asked for the most geeky non-retail person. They didn’t have what I needed, so have now booked in to see a genius.

I came home and thought I’d try and fix it again.

I came across this website.

https://www.justinsilver.com/technology/os-x-el-capitan-10-11-1-hanging-on-boot-fixed/

So, instead I tried this and logged in via Single User mode and followed this section.

The OS X Fix You’ve Been Looking For

I was ultimately able to surmise that the issue was an incompatible kernel extension (kext file). After booting into Recovery Mode, I opened Terminal. First I mounted the filesystem as read write, then navigated to /Volumes/Macintosh HD/Library/Extensions, created a new folder named ‚ÄúUnsupported‚ÄĚ and moved all the kext files into it, then rebooted.

Note: see the updated script at the very bottom of this post to automatically remove non-default kexts. If you have renamed your hard drive to something other than ‚ÄúMacintosh HD‚ÄĚ use the new name in the following commands.

1
2
3
4
5
mount -rw /
cd /Volumes/Macintosh\ HD/Library/Extensions/
mkdir Unsupported
mv *.kext Unsupported
reboot

 

So, in short, it was as I suspected, to be a suspect KEXT file.

This will get you out of trouble.

 

0-02-07-59cfb6b6844a7f864f3dd4525a69a9b6cf4b124766e54b4c2c553dc3aa21be28_1c6d9a9fe8e0ff

I hate asynchronous JS programming

Posted on Updated on

This has to be the biggest problem I face when using JS.

It’s not like VB, VBScript, BAT, BAS, C# or other serial, linear programming languages.

It drives me crazy.

I’m still of the opinion that all code should still be sequential by default, and if you want a function to be async, then you should just tell that specific call to be async, rather than the other way around. An opt in, rather than “you’re already in and tough luck”.

To make like easier (and I’ve stolen this code to post here, as it makes life easier and so I can find it again later) here is some code of a working practical example.

 

Serial or Chaining Flow

If you want to execute different promise methods sequential i.e. execute one by one, it is easy using Async/Await and the code looks like synchronous.

async function SerialFlow(){
let result1 = await doJob(1,1);
let result2 = await doJob(2,2);
let result3 = await doJob(3,3);
let finalResult = result1+result2+result3;
console.log(finalResult);
return finalResult;
}
SerialFlow();

In above method first 1 is executed and wait for one sec then 2 is started wait for 2 seconds after that 3 started to execute. 1,2,3 are executed sequentially, hence the total time is 6 seconds.

Console Output:

Start: 1
End: 1
Start: 2
End: 2
Start: 3
End: 3
6

 

Just about every other example online gives non-practical examples and use promises, observables, awaits, asyncs, call-back hell, jargon that mostly doesn’t make sense. I hope this very simple example will help you.

 

Here is my very crude example of partially working code, of which you can see there are things going on.

async function getpostcoderegion(state)
{
¬†¬†var¬†dataselection¬†=¬†document.getElementById(“dataselection”).value;
¬†¬†var¬†dateparams¬†=¬†“&date=”¬†+¬†dataselection;
// Confirm as CITY
// Confirm as REGIONAL
¬†¬†var¬†params¬†=¬†“state=”¬†+¬†state¬†+¬†dateparams;
  var xhttp =  new XMLHttpRequest();
    xhttp.onreadystatechange = await function() {
    if (this.readyState == 4 && this.status == 200) {
      citystations = JSON.parse(xhttp.responseText);
      console.log(citystations);
    }
  };
¬†¬†xhttp.open(“POST”,¬†“getpostcodecitystate.php”,¬†true);
¬†¬†xhttp.setRequestHeader(‘X-Requested-With’,¬†‘XMLHttpRequest’);
¬†¬†xhttp.setRequestHeader(‘Content-Type’,¬†‘application/x-www-form-urlencoded’);
  xhttp.send(params);
  return 1;
}

async  function postcodeboundariesshow(state_location)

{
  // Collected the postcodes of those that are for the city/metor areas in that state.
    //getpostcoderegion(state_location);
¬†¬†¬†¬†var¬†file_location¬†=¬†“../../geo_json/”¬†+¬†state_location¬†+¬†“.postcode.json”;
 geojsonLayer[state_location] = new L.GeoJSON.AJAX(file_location, {
    onEachFeature: onEachFeature,
¬†¬†¬†¬†“fillOpacity”:¬†.05,
¬†¬†¬†¬†color:¬†“#F00”,
    weight: 1,
  })
  .addTo(mymap);
¬†¬†¬†return¬†“2”;
}

 

// RUN THE MAGIC FROM THIS FUNCTION.
async function postcodeboundaries(state_location)
{

  // Collected the postcodes of those that are for the city/metor areas in that state.
    let a = await getpostcoderegion(state_location);
    let b = await postcodeboundariesshow(state_location);
}

Ionic 3 Background Geolocation

Posted on

It’s taken a long time to get to this stage, but this is just the start…

After having followed the instructions on this site, I got a long way.

But, I also only got so far as well… Here is a copy of my “home.ts” file for an app.

 

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { BackgroundGeolocation, BackgroundGeolocationConfig, BackgroundGeolocationResponse, BackgroundGeolocationEvents } from '@ionic-native/background-geolocation';
import { LocalNotifications } from '@ionic-native/local-notifications';

@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {

config: BackgroundGeolocationConfig = {
desiredAccuracy: 10,
stationaryRadius: 20,
distanceFilter: 30,
debug: true, // enable this hear sounds for background-geolocation life-cycle.
stopOnTerminate: false, // enable this to clear background location settings when the app terminates
};

missionCode: string = "";
userId: string = "";

constructor(public navCtrl: NavController,

private plt: Platform, 
private backgroundGeolocation: BackgroundGeolocation,
public globals: GlobalsProvider,
private localNotifications: LocalNotifications) {


if(this.plt.is('core') || this.plt.is('mobileweb')) {

// NO. It's a browser.
// Use a different GPS method.

} else 
{
// YES. It's a a compilerd app.


this.backgroundGeolocation.configure(this.config)
.then(() => {

this.backgroundGeolocation.on(BackgroundGeolocationEvents.location).
subscribe((location: BackgroundGeolocationResponse) => {
console.log(location);


this.showNotification(location);


// IMPORTANT: You must execute the finish method here to inform the native plugin that you're finished,
// and the background-task may be completed. You must do this regardless if your HTTP request is successful or not.
// IF YOU DON'T, ios will CRASH YOUR APP for spending too much time in the background. 
this.backgroundGeolocation.finish(); // FOR IOS ONLY
});

}); 
}

}

startBackgroundGeolocation() {
// start recording location
this.backgroundGeolocation.start();
}

stopBackgroundGeolocation() {
// If you wish to turn OFF background-tracking, call the #stop method.
this.backgroundGeolocation.stop();
}

showNotification(data){
// Schedule a single notification
this.localNotifications.schedule({
id: 1,
text: JSON.stringify(data),
sound: 'file://sound.mp3',
data: { secret: "key" }
});
}

}

 

My packages.json file looks like this:

{
"name": "My App",
"version": "0.0.1",
"author": "Ionic Framework",
"homepage": "http://ionicframework.com/",
"private": true,
"scripts": {
"start": "ionic-app-scripts serve",
"clean": "ionic-app-scripts clean",
"build": "ionic-app-scripts build",
"lint": "ionic-app-scripts lint"
},
"dependencies": {
"@angular/animations": "5.2.11",
"@angular/common": "5.2.11",
"@angular/compiler": "5.2.11",
"@angular/compiler-cli": "5.2.11",
"@angular/core": "5.2.11",
"@angular/forms": "5.2.11",
"@angular/http": "^5.2.11",
"@angular/platform-browser": "5.2.11",
"@angular/platform-browser-dynamic": "5.2.11",
"@auth0/angular-jwt": "^1.2.0",
"@babel/core": "^7.8.4",
"@ionic-native/background-geolocation": "^4.20.0",
"@ionic-native/core": "~4.11.0",
"@ionic-native/geolocation": "^4.20.0",
"@ionic-native/http": "^4.20.0",
"@ionic-native/local-notifications": "^4.20.0",
"@ionic-native/splash-screen": "~4.11.0",
"@ionic-native/status-bar": "~4.11.0",
"@ionic/storage": "^2.2.0",
"cordova-android": "^7.1.1",
"cordova-browser": "^6.0.0",
"cordova-plugin-advanced-http": "^2.4.0",
"cordova-plugin-badge": "^0.8.8",
"cordova-plugin-device": "^2.0.3",
"cordova-plugin-file": "^6.0.2",
"cordova-plugin-geolocation": "^4.0.2",
"cordova-plugin-ionic-keyboard": "^2.2.0",
"cordova-plugin-ionic-webview": "^2.5.3",
"cordova-plugin-local-notification": "^0.9.0-beta.2",
"cordova-plugin-mauron85-background-geolocation": "^3.0.1",
"cordova-plugin-splashscreen": "^5.0.3",
"cordova-plugin-whitelist": "^1.3.4",
"cordova-sqlite-storage": "^4.0.0",
"emulator": "0.1.0",
"glob": "^7.1.6",
"ionic-angular": "3.9.2",
"ionicons": "3.0.0",
"leaflet": "^1.6.0",
"leaflet-ant-path": "^1.3.0",
"leaflet-draw": "^1.0.4",
"leaflet-gps-tracker": "^1.2.1",
"leaflet-polyline": "0.0.2",
"leaflet.freedraw": "^2.0.1",
"native-run": "^0.3.0",
"node-sass": "^4.13.1",
"resolve": "^1.15.0",
"rxjs": "5.5.11",
"sw-toolbox": "3.6.0",
"zone.js": "0.8.26"
},
"devDependencies": {
"@ionic/app-scripts": "^3.2.4",
"typescript": "~2.6.2"
},
"description": "The best way to manage your searches from an emergency management control point.",
"cordova": {
"plugins": {
"cordova-plugin-geolocation": {
"GEOLOCATION_USAGE_DESCRIPTION": "To locate you"
},
"cordova-plugin-whitelist": {},
"cordova-plugin-device": {},
"cordova-plugin-splashscreen": {},
"cordova-plugin-ionic-webview": {},
"cordova-plugin-ionic-keyboard": {},
"cordova-sqlite-storage": {},
"cordova-plugin-advanced-http": {},
"cordova-plugin-mauron85-background-geolocation": {},
"cordova-plugin-local-notification": {}
},
"platforms": [
"browser",
"android"
]
}
}

 

This code is a little old, but please note, the version numbers in my packages.json file.

Leaflet Performance issues

Posted on Updated on

I’m really enjoying working with Leaflet at the moment, but this problem had plagued me for days, where all of a sudden, my performance levels dropped to almost nothing.

Basically I went from this:

this.globals.map.locate(
{ 
maxZoom: 111,
drawControl: true,
watch:true,
enableHighAccuracy:true
}).on('locationfound', (e) => {

this.locationdata = { "coords":{"latitude": e.latlng.lat, 
"longitude": e.latlng.lng,
"accuracy" : e.accuracy, 
"altitude" : e.altitude, 
"heading" : e.heading,
"speed" : e.speed,
"timestamp" : e.timestamp
}};

}

 

To this:

this.map.locate(
{
maxZoom: 111,
drawControl: true,
enableHighAccuracy:true
}).on('locationfound', (e) => {

this.locationdata = { "coords":{"latitude": e.latlng.lat,
"longitude": e.latlng.lng,
"accuracy" : e.accuracy,
"altitude" : e.altitude,
"heading" : e.heading,
"speed" : e.speed,
"timestamp" : e.timestamp
}};
}

 

What’s the difference you say?

” watch:true,”

Basically, if you have have this running like this, it will keep on checking the GPS signal in the background, and eventually cripple everything, because your phone device can’t keep up with the app. GPS time-outs will occur and things won’t complete. So, if you remove the watch:true statement, things will still work well, and you can call it every second, or every 10 seconds, or whatever your tracking needs are.

My full issue was that exponentially, the app was just slowing down to a complete halt and anything to do with the map would slow and stop working. It would begin fine, but within a few minutes, the app was unusable.

So, this is my (partial) solution. It should be enough to help you get by.

I’ve found it’s easier to do something like this:

this.subscr = Observable.interval(1000) 
.flatMap(() => this.getData())
.subscribe(data => { 
//console.log("App 1 second heartbeat"); 
// Call the GPS tracker bit
this.GetRealTimeLocationNow(); /// THIS FUNCTION INCLUDES THAT GPS METHOD
if(this.trackedRoute.length >0)
{
this.redrawPath(this.trackedRoute); 
}
});

 

So, after a couple of days thinking it was layer and mapping problems (with showing hiding markers or tracking lines and rewriting that entire part), and optimising the app even more, I think it’s pretty good now. This will be more or less confirmed over time though.

You can draw a tracking line like this too:

current_positionTrack: any [];


somefunction_etc()
{
// Show the current location on the map
if (this.current_positionTrack != undefined) 
{
 if(this.map)
  {
   this.map.removeLayer(this.current_positionTrack);
  } 
 }; 

this.current_positionTrack = leaflet.polyline(path, {color: 'red', weight: 1, opacity: 0.7, smoothFactor: 1});
this.map.addLayer(this.current_positionTrack); 
}

And even have a marker that stays on the screen on your location too, like this:

marker = null;


some_other_function_etc () //or whatever
{

// Probably should go after this in the GPS tracker bit:
// }).on('locationfound', (e) => {
// You'll figure it out.
 
 if (!this.marker) {
  this.marker = leaflet.marker(e.latlng).addTo(this.map);
 }

 if(e.latlng != null)
 {
  this.marker.setLatLng(e.latlng);
 }
}