├── .gitattributes ├── .gitignore ├── README.md ├── Samples ├── AndroidManifest.template.xml ├── CppNetworkStateSample.cbproj ├── CppNetworkStateSample.cpp ├── CppNetworkStateSample.deployproj ├── CppNetworkStateSamplePCH1.h ├── DelphiNetworkStateSample.deployproj ├── DelphiNetworkStateSample.dpr ├── DelphiNetworkStateSample.dproj ├── Entitlement.TemplateiOS.xml ├── FForm.fmx ├── FForm.pas ├── FFormCPP.cpp ├── FFormCPP.fmx ├── FFormCPP.h ├── Samples.groupproj ├── info.plist.TemplateiOS.xml ├── libReachability.a └── libReachability64.a └── Source ├── Android ├── BroadcastReceiver │ ├── UBroadcastReceiver.pas │ └── UNetworkStateBroadcastReceiver.pas └── UNetworkState.Android.pas ├── UNetworkState.pas └── iOS ├── CaptiveNetwork.pas ├── SCNetworkReachability.pas └── UNetworkState.iOS.pas /.gitattributes: -------------------------------------------------------------------------------- 1 | # Don't let git change default linebreaks 2 | *.xml text eol=lf 3 | .gitattributes text eol=lf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.local 2 | *.res 3 | *.stat 4 | *.identcache 5 | *.hpp 6 | 7 | Debug/ 8 | Release/ 9 | 10 | __history/ 11 | __recovery/ 12 | __astcache/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # firemonkey-network-state 2 | Library for managing network state in Delphi or C++ Firemonkey apps on Android and iOS. 3 | 4 | More details can be found in the accompanying article [here](https://www.code-partners.com/internet-connectivity-state-management-in-firemonkey/) 5 | -------------------------------------------------------------------------------- /Samples/AndroidManifest.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | 11 | <%uses-permission%> 12 | 13 | 21 | 22 | <%application-meta-data%> 23 | <%services%> 24 | 26 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 38 | <%activity%> 39 | <%receivers%> 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Samples/CppNetworkStateSample.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | 3 | #include 4 | #ifdef _WIN32 5 | #include 6 | #endif 7 | #pragma hdrstop 8 | #include 9 | //--------------------------------------------------------------------------- 10 | USEFORM("FFormCPP.cpp", FormSample); 11 | //--------------------------------------------------------------------------- 12 | extern "C" int FMXmain() 13 | { 14 | try 15 | { 16 | Application->Initialize(); 17 | Application->CreateForm(__classid(TFormSample), &FormSample); 18 | Application->Run(); 19 | } 20 | catch (Exception &exception) 21 | { 22 | Application->ShowException(&exception); 23 | } 24 | catch (...) 25 | { 26 | try 27 | { 28 | throw Exception(""); 29 | } 30 | catch (Exception &exception) 31 | { 32 | Application->ShowException(&exception); 33 | } 34 | } 35 | return 0; 36 | } 37 | //--------------------------------------------------------------------------- 38 | -------------------------------------------------------------------------------- /Samples/CppNetworkStateSample.deployproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 12 5 | 6 | 7 | ad051703c071eb11e2 8 | dc398986acabb53bce25b5f6a2661fdbf3da125b 9 | dc398986acabb53bce25b5f6a2661fdbf3da125b 10 | 11 | 12 | 13 | CppNetworkStateSample.app\ 14 | Default-568h@2x.png 15 | iPhone_Launch640x1136 16 | 1 17 | 18 | 19 | True 20 | 21 | 22 | CppNetworkStateSample.app\ 23 | FM_ApplicationIcon_180x180.png 24 | iPhone_AppIcon180 25 | 0 26 | 27 | 28 | True 29 | 30 | 31 | CppNetworkStateSample.app\StartUp\Documents\ 32 | libReachability64.a 33 | ProjectFile 34 | 0 35 | 36 | 37 | True 38 | 39 | 40 | CppNetworkStateSample.app\ 41 | FM_ApplicationIcon_57x57.png 42 | iPhone_AppIcon57 43 | 0 44 | 45 | 46 | True 47 | 48 | 49 | CppNetworkStateSample.app\ 50 | FM_ApplicationIcon_144x144.png 51 | iPad_AppIcon144 52 | 0 53 | 54 | 55 | True 56 | 57 | 58 | CppNetworkStateSample.app\ 59 | CppNetworkStateSample 60 | ProjectOutput 61 | 1 62 | 63 | 64 | True 65 | True 66 | 67 | 68 | CppNetworkStateSample.app\ 69 | FM_ApplicationIcon_60x60.png 70 | iPhone_AppIcon60 71 | 0 72 | 73 | 74 | True 75 | 76 | 77 | CppNetworkStateSample.app\ 78 | Default-667h@2x.png 79 | iPhone_Launch750 80 | 0 81 | 82 | 83 | True 84 | 85 | 86 | CppNetworkStateSample.app\ 87 | FM_SettingIcon_29x29.png 88 | iPad_Setting29 89 | 0 90 | 91 | 92 | True 93 | 94 | 95 | CppNetworkStateSample.app\ 96 | Default@2x.png 97 | iPhone_Launch640 98 | 1 99 | 100 | 101 | True 102 | 103 | 104 | CppNetworkStateSample.app\ 105 | FM_SettingIcon_58x58.png 106 | iPad_Setting58 107 | 0 108 | 109 | 110 | True 111 | 112 | 113 | CppNetworkStateSample.app\ 114 | Default.png 115 | iPhone_Launch320 116 | 1 117 | 118 | 119 | True 120 | 121 | 122 | CppNetworkStateSample.app\ 123 | Default-Portrait@2x.png 124 | iPad_Launch1536 125 | 1 126 | 127 | 128 | True 129 | 130 | 131 | CppNetworkStateSample.app\ 132 | FM_ApplicationIcon_72x72.png 133 | iPad_AppIcon72 134 | 0 135 | 136 | 137 | True 138 | 139 | 140 | CppNetworkStateSample.app\ 141 | Default-Landscape@2x.png 142 | iPad_Launch2048 143 | 1 144 | 145 | 146 | True 147 | 148 | 149 | CppNetworkStateSample.app\ 150 | FM_ApplicationIcon_120x120.png 151 | iPhone_AppIcon120 152 | 0 153 | 154 | 155 | True 156 | 157 | 158 | CppNetworkStateSample.app\ 159 | Default-Portrait@2x~ipad.png 160 | iPad_Launch1536x2048 161 | 0 162 | 163 | 164 | True 165 | 166 | 167 | CppNetworkStateSample.app\ 168 | FM_SpotlightSearchIcon_100x100.png 169 | iPad_SpotLight100 170 | 0 171 | 172 | 173 | True 174 | 175 | 176 | CppNetworkStateSample.app\ 177 | FM_SpotlightSearchIcon_58x58.png 178 | iPhone_Spotlight58 179 | 0 180 | 181 | 182 | True 183 | 184 | 185 | CppNetworkStateSample.app\ 186 | ResourceRules.plist 187 | ProjectiOSDeviceResourceRules 188 | 1 189 | 190 | 191 | True 192 | 193 | 194 | CppNetworkStateSample.app\ 195 | Default~ipad.png 196 | iPad_Launch768 197 | 1 198 | 199 | 200 | True 201 | 202 | 203 | CppNetworkStateSample.app\ 204 | Default-Landscape-812h@3x.png 205 | iPhone_Launch2436 206 | 0 207 | 208 | 209 | True 210 | 211 | 212 | CppNetworkStateSample.app\ 213 | Default-Portrait~ipad.png 214 | iPad_Launch768x1024 215 | 0 216 | 217 | 218 | True 219 | 220 | 221 | CppNetworkStateSample.app\ 222 | FM_ApplicationIcon_114x114.png 223 | iPhone_AppIcon114 224 | 0 225 | 226 | 227 | True 228 | 229 | 230 | CppNetworkStateSample.app\ 231 | Info.plist 232 | ProjectiOSInfoPList 233 | 1 234 | 235 | 236 | True 237 | 238 | 239 | CppNetworkStateSample.app\ 240 | FM_SpotlightSearchIcon_50x50.png 241 | iPad_SpotLight50 242 | 0 243 | 244 | 245 | True 246 | 247 | 248 | CppNetworkStateSample.app\ 249 | FM_ApplicationIcon_76x76.png 250 | iPad_AppIcon76 251 | 0 252 | 253 | 254 | True 255 | 256 | 257 | CppNetworkStateSample.app\..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF\ 258 | CppNetworkStateSample 259 | ProjectiOSDeviceDebug 260 | 1 261 | 262 | 263 | True 264 | 265 | 266 | CppNetworkStateSample.app\ 267 | FM_SpotlightSearchIcon_80x80.png 268 | iPhone_Spotlight80 269 | 0 270 | 271 | 272 | True 273 | 274 | 275 | CppNetworkStateSample.app\ 276 | FM_SpotlightSearchIcon_80x80.png 277 | iPad_SpotLight80 278 | 0 279 | 280 | 281 | True 282 | 283 | 284 | CppNetworkStateSample.app\ 285 | Default-Landscape-736h@3x.png 286 | iPhone_Launch2208 287 | 0 288 | 289 | 290 | True 291 | 292 | 293 | CppNetworkStateSample.app\ 294 | FM_SpotlightSearchIcon_40x40.png 295 | iPhone_Spotlight40 296 | 0 297 | 298 | 299 | True 300 | 301 | 302 | CppNetworkStateSample.app\ 303 | Default-736h@3x.png 304 | iPhone_Launch1242 305 | 0 306 | 307 | 308 | True 309 | 310 | 311 | CppNetworkStateSample.app\ 312 | Default-812h@3x.png 313 | iPhone_Launch1125 314 | 0 315 | 316 | 317 | True 318 | 319 | 320 | CppNetworkStateSample.app\ 321 | Default-Landscape.png 322 | iPad_Launch1024 323 | 1 324 | 325 | 326 | True 327 | 328 | 329 | CppNetworkStateSample.app\ 330 | FM_ApplicationIcon_152x152.png 331 | iPad_AppIcon152 332 | 0 333 | 334 | 335 | True 336 | 337 | 338 | CppNetworkStateSample.app\ 339 | FM_SpotlightSearchIcon_40x40.png 340 | iPad_SpotLight40 341 | 0 342 | 343 | 344 | True 345 | 346 | 347 | CppNetworkStateSample.app\ 348 | FM_ApplicationIcon_87x87.png 349 | iPhone_AppIcon87 350 | 0 351 | 352 | 353 | True 354 | 355 | 356 | CppNetworkStateSample.app\ 357 | FM_SpotlightSearchIcon_29x29.png 358 | iPhone_Spotlight29 359 | 0 360 | 361 | 362 | True 363 | 364 | 365 | CppNetworkStateSample.app\..\ 366 | CppNetworkStateSample.entitlements 367 | ProjectiOSEntitlements 368 | 1 369 | 370 | 371 | True 372 | 373 | 374 | CppNetworkStateSample.app\ 375 | Default-Landscape@2x~ipad.png 376 | iPad_Launch2048x1536 377 | 0 378 | 379 | 380 | True 381 | 382 | 383 | CppNetworkStateSample.app\ 384 | Default-Landscape~ipad.png 385 | iPad_Launch1024x768 386 | 0 387 | 388 | 389 | True 390 | 391 | 392 | 393 | 394 | CppNetworkStateSample\ 395 | cc64250.dll 396 | DependencyModule 397 | 0 398 | 399 | 400 | True 401 | 402 | 403 | CppNetworkStateSample\ 404 | borlndmm.dll 405 | DependencyModule 406 | 0 407 | 408 | 409 | True 410 | 411 | 412 | CppNetworkStateSample\ 413 | cc64250mt.dll 414 | DependencyModule 415 | 0 416 | 417 | 418 | True 419 | 420 | 421 | 422 | 423 | 424 | CppNetworkStateSample\ 425 | CppNetworkStateSample.exe 426 | ProjectOutput 427 | 0 428 | 429 | 430 | True 431 | True 432 | 433 | 434 | CppNetworkStateSample\ 435 | borlndmm.dll 436 | DependencyModule 437 | 0 438 | 439 | 440 | True 441 | 442 | 443 | CppNetworkStateSample\ 444 | cc32250.dll 445 | DependencyModule 446 | 0 447 | 448 | 449 | True 450 | 451 | 452 | CppNetworkStateSample\ 453 | cc32250mt.dll 454 | DependencyModule 455 | 0 456 | 457 | 458 | True 459 | 460 | 461 | CppNetworkStateSample\ 462 | cc32c250mt.dll 463 | DependencyModule 464 | 0 465 | 466 | 467 | True 468 | 469 | 470 | CppNetworkStateSample\ 471 | cc32c250.dll 472 | DependencyModule 473 | 0 474 | 475 | 476 | True 477 | 478 | 479 | 480 | 481 | CppNetworkStateSample.app\Contents\MacOS\ 482 | libcgstl.dylib 483 | DependencyModule 484 | 1 485 | 486 | 487 | True 488 | 489 | 490 | CppNetworkStateSample.app\Contents\MacOS\ 491 | libcgsqlite3.dylib 492 | DependencyModule 493 | 1 494 | 495 | 496 | True 497 | 498 | 499 | CppNetworkStateSample.app\Contents\MacOS\ 500 | libcgunwind.1.0.dylib 501 | DependencyModule 502 | 1 503 | 504 | 505 | True 506 | 507 | 508 | CppNetworkStateSample.app\Contents\MacOS\ 509 | libcgcrtl.dylib 510 | DependencyModule 511 | 1 512 | 513 | 514 | True 515 | 516 | 517 | 518 | 519 | CppNetworkStateSample\res\drawable-ldpi\ 520 | ic_launcher.png 521 | Android_LauncherIcon36 522 | 1 523 | 524 | 525 | True 526 | 527 | 528 | CppNetworkStateSample\res\drawable-hdpi\ 529 | ic_launcher.png 530 | Android_LauncherIcon72 531 | 1 532 | 533 | 534 | True 535 | 536 | 537 | CppNetworkStateSample\res\drawable-small\ 538 | splash_image.png 539 | Android_SplashImage426 540 | 1 541 | 542 | 543 | True 544 | 545 | 546 | CppNetworkStateSample\library\lib\mips\ 547 | libAndroidCppNetworkStateSample.so 548 | AndroidLibnativeMipsFile 549 | 1 550 | 551 | 552 | True 553 | 554 | 555 | CppNetworkStateSample\res\drawable-xxhdpi\ 556 | ic_launcher.png 557 | Android_LauncherIcon144 558 | 1 559 | 560 | 561 | True 562 | 563 | 564 | CppNetworkStateSample\library\lib\armeabi\ 565 | libAndroidCppNetworkStateSample.so 566 | AndroidLibnativeArmeabiFile 567 | 1 568 | 569 | 570 | True 571 | 572 | 573 | CppNetworkStateSample\res\values\ 574 | styles.xml 575 | AndroidSplashStyles 576 | 1 577 | 578 | 579 | True 580 | 581 | 582 | CppNetworkStateSample\res\drawable-xhdpi\ 583 | ic_launcher.png 584 | Android_LauncherIcon96 585 | 1 586 | 587 | 588 | True 589 | 590 | 591 | CppNetworkStateSample\ 592 | AndroidManifest.xml 593 | ProjectAndroidManifest 594 | 1 595 | 596 | 597 | True 598 | 599 | 600 | CppNetworkStateSample\library\lib\armeabi-v7a\ 601 | libCppNetworkStateSample.so 602 | ProjectOutput 603 | 1 604 | 605 | 606 | True 607 | True 608 | 609 | 610 | CppNetworkStateSample\res\drawable-large\ 611 | splash_image.png 612 | Android_SplashImage640 613 | 1 614 | 615 | 616 | True 617 | 618 | 619 | CppNetworkStateSample\res\drawable-xlarge\ 620 | splash_image.png 621 | Android_SplashImage960 622 | 1 623 | 624 | 625 | True 626 | 627 | 628 | CppNetworkStateSample\res\drawable\ 629 | splash_image_def.xml 630 | AndroidSplashImageDef 631 | 1 632 | 633 | 634 | True 635 | 636 | 637 | CppNetworkStateSample\res\drawable-mdpi\ 638 | ic_launcher.png 639 | Android_LauncherIcon48 640 | 1 641 | 642 | 643 | True 644 | 645 | 646 | CppNetworkStateSample\library\lib\armeabi-v7a\ 647 | gdbserver 648 | AndroidGDBServer 649 | 1 650 | 651 | 652 | True 653 | 654 | 655 | CppNetworkStateSample\res\drawable-normal\ 656 | splash_image.png 657 | Android_SplashImage470 658 | 1 659 | 660 | 661 | True 662 | 663 | 664 | CppNetworkStateSample\classes\ 665 | classes.dex 666 | AndroidClassesDexFile 667 | 1 668 | 669 | 670 | True 671 | 672 | 673 | CppNetworkStateSample\assets\internal\ 674 | libReachability64.a 675 | ProjectFile 676 | 0 677 | 678 | 679 | True 680 | 681 | 682 | 683 | 684 | CppNetworkStateSample.app\ 685 | libcgunwind.1.0.dylib 686 | DependencyModule 687 | 1 688 | 689 | 690 | True 691 | 692 | 693 | CppNetworkStateSample.app\ 694 | libPCRE.dylib 695 | DependencyModule 696 | 1 697 | 698 | 699 | True 700 | 701 | 702 | 703 | -------------------------------------------------------------------------------- /Samples/CppNetworkStateSamplePCH1.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef _WIN32 3 | #include 4 | #endif 5 | 6 | -------------------------------------------------------------------------------- /Samples/DelphiNetworkStateSample.deployproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 12 5 | 6 | 7 | ad051703c071eb11e2 8 | dc398986acabb53bce25b5f6a2661fdbf3da125b 9 | 03710820612b5ae95f0699fa6cdd35b5658bc656 10 | 6F516E0B-AB13-4A53-9AC0-6502F57376A6 11 | 12 | 13 | 14 | DelphiNetworkStateSample.app\ 15 | Default-568h@2x.png 16 | iPhone_Launch640x1136 17 | 1 18 | 19 | 20 | True 21 | 22 | 23 | DelphiNetworkStateSample.app\ 24 | FM_ApplicationIcon_144x144.png 25 | iPad_AppIcon144 26 | 0 27 | 28 | 29 | True 30 | 31 | 32 | DelphiNetworkStateSample.app\ 33 | FM_ApplicationIcon_57x57.png 34 | iPhone_AppIcon57 35 | 0 36 | 37 | 38 | True 39 | 40 | 41 | DelphiNetworkStateSample.app\ 42 | Default-667h@2x.png 43 | iPhone_Launch750 44 | 0 45 | 46 | 47 | True 48 | 49 | 50 | DelphiNetworkStateSample.app\ 51 | Default@2x.png 52 | iPhone_Launch640 53 | 1 54 | 55 | 56 | True 57 | 58 | 59 | DelphiNetworkStateSample.app\ 60 | Default-Portrait@2x.png 61 | iPad_Launch1536 62 | 1 63 | 64 | 65 | True 66 | 67 | 68 | DelphiNetworkStateSample.app\ 69 | Default.png 70 | iPhone_Launch320 71 | 1 72 | 73 | 74 | True 75 | 76 | 77 | DelphiNetworkStateSample.app\ 78 | FM_ApplicationIcon_120x120.png 79 | iPhone_AppIcon120 80 | 0 81 | 82 | 83 | True 84 | 85 | 86 | DelphiNetworkStateSample.app\ 87 | Default~ipad.png 88 | iPad_Launch768 89 | 1 90 | 91 | 92 | True 93 | 94 | 95 | DelphiNetworkStateSample.app\ 96 | FM_SpotlightSearchIcon_50x50.png 97 | iPad_SpotLight50 98 | 0 99 | 100 | 101 | True 102 | 103 | 104 | DelphiNetworkStateSample.app\ 105 | FM_ApplicationIcon_76x76.png 106 | iPad_AppIcon76 107 | 0 108 | 109 | 110 | True 111 | 112 | 113 | DelphiNetworkStateSample.app\ 114 | FM_SpotlightSearchIcon_80x80.png 115 | iPad_SpotLight80 116 | 0 117 | 118 | 119 | True 120 | 121 | 122 | DelphiNetworkStateSample.app\ 123 | FM_SpotlightSearchIcon_40x40.png 124 | iPhone_Spotlight40 125 | 0 126 | 127 | 128 | True 129 | 130 | 131 | DelphiNetworkStateSample.app\ 132 | Default-736h@3x.png 133 | iPhone_Launch1242 134 | 0 135 | 136 | 137 | True 138 | 139 | 140 | DelphiNetworkStateSample.app\ 141 | FM_SpotlightSearchIcon_40x40.png 142 | iPad_SpotLight40 143 | 0 144 | 145 | 146 | True 147 | 148 | 149 | DelphiNetworkStateSample.app\ 150 | FM_ApplicationIcon_180x180.png 151 | iPhone_AppIcon180 152 | 0 153 | 154 | 155 | True 156 | 157 | 158 | DelphiNetworkStateSample.app\ 159 | FM_ApplicationIcon_60x60.png 160 | iPhone_AppIcon60 161 | 0 162 | 163 | 164 | True 165 | 166 | 167 | DelphiNetworkStateSample.app\ 168 | FM_SettingIcon_29x29.png 169 | iPad_Setting29 170 | 0 171 | 172 | 173 | True 174 | 175 | 176 | DelphiNetworkStateSample.app\ 177 | FM_SettingIcon_58x58.png 178 | iPad_Setting58 179 | 0 180 | 181 | 182 | True 183 | 184 | 185 | DelphiNetworkStateSample.app\ 186 | Info.plist 187 | ProjectiOSInfoPList 188 | 1 189 | 190 | 191 | True 192 | 193 | 194 | DelphiNetworkStateSample.app\ 195 | FM_ApplicationIcon_72x72.png 196 | iPad_AppIcon72 197 | 0 198 | 199 | 200 | True 201 | 202 | 203 | DelphiNetworkStateSample.app\ 204 | Default-Portrait@2x~ipad.png 205 | iPad_Launch1536x2048 206 | 0 207 | 208 | 209 | True 210 | 211 | 212 | DelphiNetworkStateSample.app\ 213 | Default-Landscape@2x.png 214 | iPad_Launch2048 215 | 1 216 | 217 | 218 | True 219 | 220 | 221 | DelphiNetworkStateSample.app\ 222 | FM_SpotlightSearchIcon_100x100.png 223 | iPad_SpotLight100 224 | 0 225 | 226 | 227 | True 228 | 229 | 230 | DelphiNetworkStateSample.app\ 231 | FM_SpotlightSearchIcon_58x58.png 232 | iPhone_Spotlight58 233 | 0 234 | 235 | 236 | True 237 | 238 | 239 | DelphiNetworkStateSample.app\..\ 240 | DelphiNetworkStateSample.entitlements 241 | ProjectiOSEntitlements 242 | 1 243 | 244 | 245 | True 246 | 247 | 248 | DelphiNetworkStateSample.app\ 249 | Default-Landscape-812h@3x.png 250 | iPhone_Launch2436 251 | 0 252 | 253 | 254 | True 255 | 256 | 257 | DelphiNetworkStateSample.app\ 258 | Default-Portrait~ipad.png 259 | iPad_Launch768x1024 260 | 0 261 | 262 | 263 | True 264 | 265 | 266 | DelphiNetworkStateSample.app\ 267 | FM_ApplicationIcon_114x114.png 268 | iPhone_AppIcon114 269 | 0 270 | 271 | 272 | True 273 | 274 | 275 | DelphiNetworkStateSample.app\ 276 | DelphiNetworkStateSample 277 | ProjectOutput 278 | 1 279 | 280 | 281 | True 282 | True 283 | 284 | 285 | DelphiNetworkStateSample.app\ 286 | FM_SpotlightSearchIcon_80x80.png 287 | iPhone_Spotlight80 288 | 0 289 | 290 | 291 | True 292 | 293 | 294 | DelphiNetworkStateSample.app\ 295 | Default-Landscape-736h@3x.png 296 | iPhone_Launch2208 297 | 0 298 | 299 | 300 | True 301 | 302 | 303 | DelphiNetworkStateSample.app\ 304 | Default-812h@3x.png 305 | iPhone_Launch1125 306 | 0 307 | 308 | 309 | True 310 | 311 | 312 | DelphiNetworkStateSample.app\ 313 | Default-Landscape.png 314 | iPad_Launch1024 315 | 1 316 | 317 | 318 | True 319 | 320 | 321 | DelphiNetworkStateSample.app\..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF\ 322 | DelphiNetworkStateSample 323 | ProjectiOSDeviceDebug 324 | 1 325 | 326 | 327 | True 328 | 329 | 330 | DelphiNetworkStateSample.app\ 331 | FM_ApplicationIcon_152x152.png 332 | iPad_AppIcon152 333 | 0 334 | 335 | 336 | True 337 | 338 | 339 | DelphiNetworkStateSample.app\ 340 | FM_ApplicationIcon_87x87.png 341 | iPhone_AppIcon87 342 | 0 343 | 344 | 345 | True 346 | 347 | 348 | DelphiNetworkStateSample.app\ 349 | FM_SpotlightSearchIcon_29x29.png 350 | iPhone_Spotlight29 351 | 0 352 | 353 | 354 | True 355 | 356 | 357 | DelphiNetworkStateSample.app\ 358 | ResourceRules.plist 359 | ProjectiOSDeviceResourceRules 360 | 1 361 | 362 | 363 | True 364 | 365 | 366 | DelphiNetworkStateSample.app\ 367 | Default-Landscape@2x~ipad.png 368 | iPad_Launch2048x1536 369 | 0 370 | 371 | 372 | True 373 | 374 | 375 | DelphiNetworkStateSample.app\ 376 | Default-Landscape~ipad.png 377 | iPad_Launch1024x768 378 | 0 379 | 380 | 381 | True 382 | 383 | 384 | 385 | 386 | 387 | DelphiNetworkStateSample.app\ 388 | FM_ApplicationIcon_87x87.png 389 | iPhone_AppIcon87 390 | 0 391 | 392 | 393 | True 394 | 395 | 396 | DelphiNetworkStateSample.app\ 397 | FM_ApplicationIcon_72x72.png 398 | iPad_AppIcon72 399 | 0 400 | 401 | 402 | True 403 | 404 | 405 | DelphiNetworkStateSample.app\ 406 | FM_SpotlightSearchIcon_100x100.png 407 | iPad_SpotLight100 408 | 0 409 | 410 | 411 | True 412 | 413 | 414 | DelphiNetworkStateSample.app\ 415 | Default-Landscape-736h@3x.png 416 | iPhone_Launch2208 417 | 0 418 | 419 | 420 | True 421 | 422 | 423 | DelphiNetworkStateSample.app\ 424 | Default-Portrait@2x~ipad.png 425 | iPad_Launch1536x2048 426 | 0 427 | 428 | 429 | True 430 | 431 | 432 | DelphiNetworkStateSample.app\ 433 | Default-Portrait@2x.png 434 | iPad_Launch1536 435 | 1 436 | 437 | 438 | True 439 | 440 | 441 | DelphiNetworkStateSample.app\ 442 | Default.png 443 | iPhone_Launch320 444 | 1 445 | 446 | 447 | True 448 | 449 | 450 | DelphiNetworkStateSample.app\ 451 | FM_SpotlightSearchIcon_80x80.png 452 | iPhone_Spotlight80 453 | 0 454 | 455 | 456 | True 457 | 458 | 459 | DelphiNetworkStateSample.app\ 460 | Default~ipad.png 461 | iPad_Launch768 462 | 1 463 | 464 | 465 | True 466 | 467 | 468 | DelphiNetworkStateSample.app\..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF\ 469 | DelphiNetworkStateSample 470 | ProjectiOSDeviceDebug 471 | 1 472 | 473 | 474 | True 475 | 476 | 477 | DelphiNetworkStateSample.app\ 478 | Default-667h@2x.png 479 | iPhone_Launch750 480 | 0 481 | 482 | 483 | True 484 | 485 | 486 | DelphiNetworkStateSample.app\ 487 | FM_ApplicationIcon_152x152.png 488 | iPad_AppIcon152 489 | 0 490 | 491 | 492 | True 493 | 494 | 495 | DelphiNetworkStateSample.app\ 496 | Default-Landscape-812h@3x.png 497 | iPhone_Launch2436 498 | 0 499 | 500 | 501 | True 502 | 503 | 504 | DelphiNetworkStateSample.app\..\ 505 | DelphiNetworkStateSample.entitlements 506 | ProjectiOSEntitlements 507 | 1 508 | 509 | 510 | True 511 | 512 | 513 | DelphiNetworkStateSample.app\ 514 | Default-Portrait~ipad.png 515 | iPad_Launch768x1024 516 | 0 517 | 518 | 519 | True 520 | 521 | 522 | DelphiNetworkStateSample.app\ 523 | Info.plist 524 | ProjectiOSInfoPList 525 | 1 526 | 527 | 528 | True 529 | 530 | 531 | DelphiNetworkStateSample.app\ 532 | FM_ApplicationIcon_120x120.png 533 | iPhone_AppIcon120 534 | 0 535 | 536 | 537 | True 538 | 539 | 540 | DelphiNetworkStateSample.app\ 541 | FM_SpotlightSearchIcon_40x40.png 542 | iPad_SpotLight40 543 | 0 544 | 545 | 546 | True 547 | 548 | 549 | DelphiNetworkStateSample.app\ 550 | FM_SpotlightSearchIcon_80x80.png 551 | iPad_SpotLight80 552 | 0 553 | 554 | 555 | True 556 | 557 | 558 | DelphiNetworkStateSample.app\ 559 | FM_ApplicationIcon_57x57.png 560 | iPhone_AppIcon57 561 | 0 562 | 563 | 564 | True 565 | 566 | 567 | DelphiNetworkStateSample.app\ 568 | ResourceRules.plist 569 | ProjectiOSDeviceResourceRules 570 | 1 571 | 572 | 573 | True 574 | 575 | 576 | DelphiNetworkStateSample.app\ 577 | FM_SpotlightSearchIcon_29x29.png 578 | iPhone_Spotlight29 579 | 0 580 | 581 | 582 | True 583 | 584 | 585 | DelphiNetworkStateSample.app\ 586 | Default-568h@2x.png 587 | iPhone_Launch640x1136 588 | 1 589 | 590 | 591 | True 592 | 593 | 594 | DelphiNetworkStateSample.app\ 595 | Default-812h@3x.png 596 | iPhone_Launch1125 597 | 0 598 | 599 | 600 | True 601 | 602 | 603 | DelphiNetworkStateSample.app\ 604 | Default-Landscape@2x.png 605 | iPad_Launch2048 606 | 1 607 | 608 | 609 | True 610 | 611 | 612 | DelphiNetworkStateSample.app\ 613 | FM_SpotlightSearchIcon_40x40.png 614 | iPhone_Spotlight40 615 | 0 616 | 617 | 618 | True 619 | 620 | 621 | DelphiNetworkStateSample.app\ 622 | FM_SpotlightSearchIcon_50x50.png 623 | iPad_SpotLight50 624 | 0 625 | 626 | 627 | True 628 | 629 | 630 | DelphiNetworkStateSample.app\ 631 | Default@2x.png 632 | iPhone_Launch640 633 | 1 634 | 635 | 636 | True 637 | 638 | 639 | DelphiNetworkStateSample.app\ 640 | FM_ApplicationIcon_144x144.png 641 | iPad_AppIcon144 642 | 0 643 | 644 | 645 | True 646 | 647 | 648 | DelphiNetworkStateSample.app\ 649 | Default-Landscape@2x~ipad.png 650 | iPad_Launch2048x1536 651 | 0 652 | 653 | 654 | True 655 | 656 | 657 | DelphiNetworkStateSample.app\ 658 | FM_SettingIcon_58x58.png 659 | iPad_Setting58 660 | 0 661 | 662 | 663 | True 664 | 665 | 666 | DelphiNetworkStateSample.app\ 667 | DelphiNetworkStateSample 668 | ProjectOutput 669 | 1 670 | 671 | 672 | True 673 | True 674 | 675 | 676 | DelphiNetworkStateSample.app\ 677 | Default-736h@3x.png 678 | iPhone_Launch1242 679 | 0 680 | 681 | 682 | True 683 | 684 | 685 | DelphiNetworkStateSample.app\ 686 | FM_SpotlightSearchIcon_58x58.png 687 | iPhone_Spotlight58 688 | 0 689 | 690 | 691 | True 692 | 693 | 694 | DelphiNetworkStateSample.app\ 695 | FM_ApplicationIcon_114x114.png 696 | iPhone_AppIcon114 697 | 0 698 | 699 | 700 | True 701 | 702 | 703 | DelphiNetworkStateSample.app\ 704 | FM_ApplicationIcon_180x180.png 705 | iPhone_AppIcon180 706 | 0 707 | 708 | 709 | True 710 | 711 | 712 | DelphiNetworkStateSample.app\ 713 | FM_ApplicationIcon_60x60.png 714 | iPhone_AppIcon60 715 | 0 716 | 717 | 718 | True 719 | 720 | 721 | DelphiNetworkStateSample.app\ 722 | FM_SettingIcon_29x29.png 723 | iPad_Setting29 724 | 0 725 | 726 | 727 | True 728 | 729 | 730 | DelphiNetworkStateSample.app\ 731 | Default-Landscape~ipad.png 732 | iPad_Launch1024x768 733 | 0 734 | 735 | 736 | True 737 | 738 | 739 | DelphiNetworkStateSample.app\ 740 | Default-Landscape.png 741 | iPad_Launch1024 742 | 1 743 | 744 | 745 | True 746 | 747 | 748 | DelphiNetworkStateSample.app\ 749 | FM_ApplicationIcon_76x76.png 750 | iPad_AppIcon76 751 | 0 752 | 753 | 754 | True 755 | 756 | 757 | 758 | 759 | DelphiNetworkStateSample\ 760 | DelphiNetworkStateSample.exe 761 | ProjectOutput 762 | 0 763 | 764 | 765 | True 766 | True 767 | 768 | 769 | 770 | 771 | 772 | DelphiNetworkStateSample.app\Contents\MacOS\ 773 | libcgsqlite3.dylib 774 | DependencyModule 775 | 1 776 | 777 | 778 | True 779 | 780 | 781 | DelphiNetworkStateSample.app\Contents\MacOS\ 782 | libcgunwind.1.0.dylib 783 | DependencyModule 784 | 1 785 | 786 | 787 | True 788 | 789 | 790 | 791 | 792 | DelphiNetworkStateSample\res\drawable-small\ 793 | splash_image.png 794 | Android_SplashImage426 795 | 1 796 | 797 | 798 | True 799 | 800 | 801 | DelphiNetworkStateSample\res\drawable\ 802 | splash_image_def.xml 803 | AndroidSplashImageDef 804 | 1 805 | 806 | 807 | True 808 | 809 | 810 | DelphiNetworkStateSample\library\lib\armeabi-v7a\ 811 | libDelphiNetworkStateSample.so 812 | ProjectOutput 813 | 1 814 | 815 | 816 | True 817 | True 818 | 819 | 820 | DelphiNetworkStateSample\res\drawable-large\ 821 | splash_image.png 822 | Android_SplashImage640 823 | 1 824 | 825 | 826 | True 827 | 828 | 829 | DelphiNetworkStateSample\res\drawable-mdpi\ 830 | ic_launcher.png 831 | Android_LauncherIcon48 832 | 1 833 | 834 | 835 | True 836 | 837 | 838 | DelphiNetworkStateSample\classes\ 839 | classes.dex 840 | AndroidClassesDexFile 841 | 1 842 | 843 | 844 | True 845 | 846 | 847 | DelphiNetworkStateSample\res\values\ 848 | styles.xml 849 | AndroidSplashStyles 850 | 1 851 | 852 | 853 | True 854 | 855 | 856 | DelphiNetworkStateSample\res\drawable-ldpi\ 857 | ic_launcher.png 858 | Android_LauncherIcon36 859 | 1 860 | 861 | 862 | True 863 | 864 | 865 | DelphiNetworkStateSample\res\drawable-hdpi\ 866 | ic_launcher.png 867 | Android_LauncherIcon72 868 | 1 869 | 870 | 871 | True 872 | 873 | 874 | DelphiNetworkStateSample\library\lib\mips\ 875 | libAndroidDelphiNetworkStateSample.so 876 | AndroidLibnativeMipsFile 877 | 1 878 | 879 | 880 | True 881 | 882 | 883 | DelphiNetworkStateSample\ 884 | AndroidManifest.xml 885 | ProjectAndroidManifest 886 | 1 887 | 888 | 889 | True 890 | 891 | 892 | DelphiNetworkStateSample\library\lib\armeabi\ 893 | libAndroidDelphiNetworkStateSample.so 894 | AndroidLibnativeArmeabiFile 895 | 1 896 | 897 | 898 | True 899 | 900 | 901 | DelphiNetworkStateSample\res\drawable-xxhdpi\ 902 | ic_launcher.png 903 | Android_LauncherIcon144 904 | 1 905 | 906 | 907 | True 908 | 909 | 910 | DelphiNetworkStateSample\res\drawable-xhdpi\ 911 | ic_launcher.png 912 | Android_LauncherIcon96 913 | 1 914 | 915 | 916 | True 917 | 918 | 919 | DelphiNetworkStateSample\res\drawable-xlarge\ 920 | splash_image.png 921 | Android_SplashImage960 922 | 1 923 | 924 | 925 | True 926 | 927 | 928 | DelphiNetworkStateSample\library\lib\armeabi-v7a\ 929 | gdbserver 930 | AndroidGDBServer 931 | 1 932 | 933 | 934 | True 935 | 936 | 937 | DelphiNetworkStateSample\res\drawable-normal\ 938 | splash_image.png 939 | Android_SplashImage470 940 | 1 941 | 942 | 943 | True 944 | 945 | 946 | 947 | 948 | DelphiNetworkStateSample.app\ 949 | FM_ApplicationIcon_144x144.png 950 | iPad_AppIcon144 951 | 0 952 | 953 | 954 | True 955 | 956 | 957 | DelphiNetworkStateSample.app\ 958 | FM_SpotlightSearchIcon_100x100.png 959 | iPad_SpotLight100 960 | 0 961 | 962 | 963 | True 964 | 965 | 966 | DelphiNetworkStateSample.app\ 967 | FM_SpotlightSearchIcon_58x58.png 968 | iPhone_Spotlight58 969 | 0 970 | 971 | 972 | True 973 | 974 | 975 | DelphiNetworkStateSample.app\ 976 | FM_ApplicationIcon_114x114.png 977 | iPhone_AppIcon114 978 | 0 979 | 980 | 981 | True 982 | 983 | 984 | DelphiNetworkStateSample.app\ 985 | FM_ApplicationIcon_152x152.png 986 | iPad_AppIcon152 987 | 0 988 | 989 | 990 | True 991 | 992 | 993 | DelphiNetworkStateSample.app\ 994 | Default-667h@2x.png 995 | iPhone_Launch750 996 | 0 997 | 998 | 999 | True 1000 | 1001 | 1002 | DelphiNetworkStateSample.app\ 1003 | FM_ApplicationIcon_72x72.png 1004 | iPad_AppIcon72 1005 | 0 1006 | 1007 | 1008 | True 1009 | 1010 | 1011 | DelphiNetworkStateSample.app\ 1012 | libcgunwind.1.0.dylib 1013 | DependencyModule 1014 | 1 1015 | 1016 | 1017 | True 1018 | 1019 | 1020 | DelphiNetworkStateSample.app\ 1021 | Default-Portrait~ipad.png 1022 | iPad_Launch768x1024 1023 | 0 1024 | 1025 | 1026 | True 1027 | 1028 | 1029 | DelphiNetworkStateSample.app\ 1030 | Default@2x.png 1031 | iPhone_Launch640 1032 | 1 1033 | 1034 | 1035 | True 1036 | 1037 | 1038 | DelphiNetworkStateSample.app\ 1039 | FM_SpotlightSearchIcon_40x40.png 1040 | iPhone_Spotlight40 1041 | 0 1042 | 1043 | 1044 | True 1045 | 1046 | 1047 | DelphiNetworkStateSample.app\ 1048 | Default-Landscape-812h@3x.png 1049 | iPhone_Launch2436 1050 | 0 1051 | 1052 | 1053 | True 1054 | 1055 | 1056 | DelphiNetworkStateSample.app\ 1057 | FM_ApplicationIcon_87x87.png 1058 | iPhone_AppIcon87 1059 | 0 1060 | 1061 | 1062 | True 1063 | 1064 | 1065 | DelphiNetworkStateSample.app\ 1066 | Default.png 1067 | iPhone_Launch320 1068 | 1 1069 | 1070 | 1071 | True 1072 | 1073 | 1074 | DelphiNetworkStateSample.app\ 1075 | FM_ApplicationIcon_180x180.png 1076 | iPhone_AppIcon180 1077 | 0 1078 | 1079 | 1080 | True 1081 | 1082 | 1083 | DelphiNetworkStateSample.app\ 1084 | FM_SettingIcon_58x58.png 1085 | iPad_Setting58 1086 | 0 1087 | 1088 | 1089 | True 1090 | 1091 | 1092 | DelphiNetworkStateSample.app\ 1093 | FM_SpotlightSearchIcon_80x80.png 1094 | iPhone_Spotlight80 1095 | 0 1096 | 1097 | 1098 | True 1099 | 1100 | 1101 | DelphiNetworkStateSample.app\ 1102 | FM_SpotlightSearchIcon_80x80.png 1103 | iPad_SpotLight80 1104 | 0 1105 | 1106 | 1107 | True 1108 | 1109 | 1110 | DelphiNetworkStateSample.app\ 1111 | Default-Portrait@2x~ipad.png 1112 | iPad_Launch1536x2048 1113 | 0 1114 | 1115 | 1116 | True 1117 | 1118 | 1119 | DelphiNetworkStateSample.app\ 1120 | FM_ApplicationIcon_120x120.png 1121 | iPhone_AppIcon120 1122 | 0 1123 | 1124 | 1125 | True 1126 | 1127 | 1128 | DelphiNetworkStateSample.app\ 1129 | FM_SpotlightSearchIcon_50x50.png 1130 | iPad_SpotLight50 1131 | 0 1132 | 1133 | 1134 | True 1135 | 1136 | 1137 | DelphiNetworkStateSample.app\ 1138 | Default-568h@2x.png 1139 | iPhone_Launch640x1136 1140 | 1 1141 | 1142 | 1143 | True 1144 | 1145 | 1146 | DelphiNetworkStateSample.app\ 1147 | Default-Landscape.png 1148 | iPad_Launch1024 1149 | 1 1150 | 1151 | 1152 | True 1153 | 1154 | 1155 | DelphiNetworkStateSample.app\ 1156 | Default-812h@3x.png 1157 | iPhone_Launch1125 1158 | 0 1159 | 1160 | 1161 | True 1162 | 1163 | 1164 | DelphiNetworkStateSample.app\ 1165 | FM_SpotlightSearchIcon_40x40.png 1166 | iPad_SpotLight40 1167 | 0 1168 | 1169 | 1170 | True 1171 | 1172 | 1173 | DelphiNetworkStateSample.app\ 1174 | FM_ApplicationIcon_60x60.png 1175 | iPhone_AppIcon60 1176 | 0 1177 | 1178 | 1179 | True 1180 | 1181 | 1182 | DelphiNetworkStateSample.app\ 1183 | Default-Portrait@2x.png 1184 | iPad_Launch1536 1185 | 1 1186 | 1187 | 1188 | True 1189 | 1190 | 1191 | DelphiNetworkStateSample.app\ 1192 | Default-736h@3x.png 1193 | iPhone_Launch1242 1194 | 0 1195 | 1196 | 1197 | True 1198 | 1199 | 1200 | DelphiNetworkStateSample.app\ 1201 | Default~ipad.png 1202 | iPad_Launch768 1203 | 1 1204 | 1205 | 1206 | True 1207 | 1208 | 1209 | DelphiNetworkStateSample.app\ 1210 | Info.plist 1211 | ProjectiOSInfoPList 1212 | 1 1213 | 1214 | 1215 | True 1216 | 1217 | 1218 | DelphiNetworkStateSample.app\ 1219 | DelphiNetworkStateSample 1220 | ProjectOutput 1221 | 1 1222 | 1223 | 1224 | True 1225 | True 1226 | 1227 | 1228 | DelphiNetworkStateSample.app\ 1229 | Default-Landscape@2x~ipad.png 1230 | iPad_Launch2048x1536 1231 | 0 1232 | 1233 | 1234 | True 1235 | 1236 | 1237 | DelphiNetworkStateSample.app\ 1238 | DelphiNetworkStateSample.rsm 1239 | DebugSymbols 1240 | 1 1241 | 1242 | 1243 | True 1244 | 1245 | 1246 | DelphiNetworkStateSample.app\ 1247 | Default-Landscape~ipad.png 1248 | iPad_Launch1024x768 1249 | 0 1250 | 1251 | 1252 | True 1253 | 1254 | 1255 | DelphiNetworkStateSample.app\ 1256 | FM_ApplicationIcon_76x76.png 1257 | iPad_AppIcon76 1258 | 0 1259 | 1260 | 1261 | True 1262 | 1263 | 1264 | DelphiNetworkStateSample.app\ 1265 | libPCRE.dylib 1266 | DependencyModule 1267 | 1 1268 | 1269 | 1270 | True 1271 | 1272 | 1273 | DelphiNetworkStateSample.app\ 1274 | Default-Landscape-736h@3x.png 1275 | iPhone_Launch2208 1276 | 0 1277 | 1278 | 1279 | True 1280 | 1281 | 1282 | DelphiNetworkStateSample.app\ 1283 | FM_ApplicationIcon_57x57.png 1284 | iPhone_AppIcon57 1285 | 0 1286 | 1287 | 1288 | True 1289 | 1290 | 1291 | DelphiNetworkStateSample.app\ 1292 | Default-Landscape@2x.png 1293 | iPad_Launch2048 1294 | 1 1295 | 1296 | 1297 | True 1298 | 1299 | 1300 | DelphiNetworkStateSample.app\ 1301 | DelphiNetworkStateSample.entitlements 1302 | ProjectiOSEntitlements 1303 | 0 1304 | 1305 | 1306 | True 1307 | 1308 | 1309 | DelphiNetworkStateSample.app\ 1310 | FM_SpotlightSearchIcon_29x29.png 1311 | iPhone_Spotlight29 1312 | 0 1313 | 1314 | 1315 | True 1316 | 1317 | 1318 | DelphiNetworkStateSample.app\ 1319 | FM_SettingIcon_29x29.png 1320 | iPad_Setting29 1321 | 0 1322 | 1323 | 1324 | True 1325 | 1326 | 1327 | 1328 | -------------------------------------------------------------------------------- /Samples/DelphiNetworkStateSample.dpr: -------------------------------------------------------------------------------- 1 | program DelphiNetworkStateSample; 2 | 3 | uses 4 | System.StartUpCopy, 5 | FMX.Forms, 6 | FForm in 'FForm.pas' {FormSample}, 7 | UNetworkState in '..\Source\UNetworkState.pas', 8 | UBroadcastReceiver in '..\Source\Android\BroadcastReceiver\UBroadcastReceiver.pas', 9 | UNetworkStateBroadcastReceiver in '..\Source\Android\BroadcastReceiver\UNetworkStateBroadcastReceiver.pas', 10 | UNetworkState.Android in '..\Source\Android\UNetworkState.Android.pas', 11 | CaptiveNetwork in '..\Source\iOS\CaptiveNetwork.pas', 12 | SCNetworkReachability in '..\Source\iOS\SCNetworkReachability.pas', 13 | UNetworkState.iOS in '..\Source\iOS\UNetworkState.iOS.pas'; 14 | 15 | {$R *.res} 16 | 17 | begin 18 | Application.Initialize; 19 | Application.CreateForm(TFormSample, FormSample); 20 | Application.Run; 21 | end. 22 | -------------------------------------------------------------------------------- /Samples/Entitlement.TemplateiOS.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | <%getTaskAllowKey%> 6 | <%applicationIdentifier%> 7 | <%pushNotificationKey%> 8 | <%keychainAccessGroups%> 9 | 10 | 11 | -------------------------------------------------------------------------------- /Samples/FForm.fmx: -------------------------------------------------------------------------------- 1 | object FormSample: TFormSample 2 | Left = 0 3 | Top = 0 4 | Caption = 'Form5' 5 | ClientHeight = 480 6 | ClientWidth = 357 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | OnCreate = FormCreate 11 | DesignerMasterStyle = 0 12 | object Memo1: TMemo 13 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] 14 | DataDetectorTypes = [] 15 | Align = Client 16 | Size.Width = 357.000000000000000000 17 | Size.Height = 430.000000000000000000 18 | Size.PlatformDefault = False 19 | TabOrder = 0 20 | Viewport.Width = 353.000000000000000000 21 | Viewport.Height = 426.000000000000000000 22 | end 23 | object Layout1: TLayout 24 | Align = Bottom 25 | Position.Y = 430.000000000000000000 26 | Size.Width = 357.000000000000000000 27 | Size.Height = 50.000000000000000000 28 | Size.PlatformDefault = False 29 | TabOrder = 1 30 | object Button1: TButton 31 | Align = Center 32 | Size.Width = 144.000000000000000000 33 | Size.Height = 36.000000000000000000 34 | Size.PlatformDefault = False 35 | TabOrder = 0 36 | Text = 'Get current state' 37 | OnClick = Button1Click 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /Samples/FForm.pas: -------------------------------------------------------------------------------- 1 | unit FForm; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, 7 | FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts, 8 | FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, UNetworkState; 9 | 10 | type 11 | TFormSample = class(TForm) 12 | Memo1: TMemo; 13 | Button1: TButton; 14 | Layout1: TLayout; 15 | procedure FormCreate(Sender: TObject); 16 | procedure Button1Click(Sender: TObject); 17 | private 18 | FNetworkState: TNetworkState; 19 | protected 20 | procedure DoOnChange(Sender: TObject; Value: TNetworkStateValue); 21 | public 22 | 23 | end; 24 | 25 | var 26 | FormSample: TFormSample; 27 | 28 | implementation 29 | 30 | {$R *.fmx} 31 | 32 | procedure TFormSample.FormCreate(Sender: TObject); 33 | begin 34 | self.FNetworkState := TNetworkState.Factory(self, DoOnChange); 35 | 36 | if self.FNetworkState.CurrentValue = nsConnectedWifi then 37 | self.Memo1.Lines.Add('On startup: Connected with WiFi') 38 | else if self.FNetworkState.CurrentValue = nsConnectedMobileData then 39 | self.Memo1.Lines.Add('On startup: Connected with mobile data') 40 | else if self.FNetworkState.CurrentValue = nsDisconnected then 41 | self.Memo1.Lines.Add('On startup: Disconnected') 42 | else 43 | self.Memo1.Lines.Add('On startup: Unknown'); 44 | end; 45 | 46 | procedure TFormSample.DoOnChange(Sender: TObject; Value: TNetworkStateValue); 47 | begin 48 | if Value = nsConnectedWifi then 49 | self.Memo1.Lines.Add('On change: Connected with WiFi') 50 | else if Value = nsConnectedMobileData then 51 | self.Memo1.Lines.Add('On change: Connected with mobile data') 52 | else if self.FNetworkState.CurrentValue = nsDisconnected then 53 | self.Memo1.Lines.Add('On change: Disconnected') 54 | else 55 | self.Memo1.Lines.Add('On change: Unknown'); 56 | end; 57 | 58 | procedure TFormSample.Button1Click(Sender: TObject); 59 | begin 60 | if self.FNetworkState.CurrentValue = nsConnectedWifi then 61 | self.Memo1.Lines.Add('Button1 Click: Connected with WiFi') 62 | else if self.FNetworkState.CurrentValue = nsConnectedMobileData then 63 | self.Memo1.Lines.Add('Button1 Click: Connected with mobile data') 64 | else if self.FNetworkState.CurrentValue = nsDisconnected then 65 | self.Memo1.Lines.Add('Button1 Click: Disconnected') 66 | else 67 | self.Memo1.Lines.Add('Button1 Click: Unknown'); 68 | end; 69 | 70 | end. 71 | -------------------------------------------------------------------------------- /Samples/FFormCPP.cpp: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | 3 | #include 4 | #pragma hdrstop 5 | 6 | #include "FFormCPP.h" 7 | //--------------------------------------------------------------------------- 8 | #pragma package(smart_init) 9 | #pragma resource "*.fmx" 10 | TFormSample *FormSample; 11 | //--------------------------------------------------------------------------- 12 | __fastcall TFormSample::TFormSample(TComponent* Owner) 13 | : TForm(Owner) 14 | { 15 | this->FNetworkState = TNetworkState::Factory(this, this->DoOnNetworkStateChanged); 16 | 17 | if (this->FNetworkState->CurrentValue == nsConnectedWifi) { 18 | this->Memo1->Lines->Add(L"On startup: Connected with WiFi"); 19 | } else if (this->FNetworkState->CurrentValue == nsConnectedMobileData) { 20 | this->Memo1->Lines->Add(L"On startup: Connected with mobile data"); 21 | } else if (this->FNetworkState->CurrentValue == nsDisconnected) { 22 | this->Memo1->Lines->Add(L"On startup: Disconnected"); 23 | } else { 24 | this->Memo1->Lines->Add(L"On startup: Unknown"); 25 | } 26 | } 27 | 28 | void __fastcall TFormSample::Button1Click(TObject *Sender) 29 | { 30 | if (this->FNetworkState->CurrentValue == nsConnectedWifi) { 31 | this->Memo1->Lines->Add(L"Button1 Click: Connected with WiFi"); 32 | } else if (this->FNetworkState->CurrentValue == nsConnectedMobileData) { 33 | this->Memo1->Lines->Add(L"Button1 Click: Connected with mobile data"); 34 | } else if (this->FNetworkState->CurrentValue == nsDisconnected) { 35 | this->Memo1->Lines->Add(L"Button1 Click: Disconnected"); 36 | } else { 37 | this->Memo1->Lines->Add(L"Button1 Click: Unknown"); 38 | } 39 | } 40 | 41 | void __fastcall TFormSample::DoOnNetworkStateChanged(TObject* Sender, TNetworkStateValue Value) 42 | { 43 | if (this->FNetworkState->CurrentValue == nsConnectedWifi) { 44 | this->Memo1->Lines->Add(L"On change: Connected with WiFi"); 45 | } else if (this->FNetworkState->CurrentValue == nsConnectedMobileData) { 46 | this->Memo1->Lines->Add(L"On change: Connected with mobile data"); 47 | } else if (this->FNetworkState->CurrentValue == nsDisconnected) { 48 | this->Memo1->Lines->Add(L"On change: Disconnected"); 49 | } else { 50 | this->Memo1->Lines->Add(L"On change: Unknown"); 51 | } 52 | } 53 | //--------------------------------------------------------------------------- 54 | -------------------------------------------------------------------------------- /Samples/FFormCPP.fmx: -------------------------------------------------------------------------------- 1 | object FormSample: TFormSample 2 | Left = 0 3 | Top = 0 4 | Caption = 'FormSample' 5 | ClientHeight = 480 6 | ClientWidth = 368 7 | FormFactor.Width = 320 8 | FormFactor.Height = 480 9 | FormFactor.Devices = [Desktop] 10 | DesignerMasterStyle = 0 11 | object Layout1: TLayout 12 | Align = Bottom 13 | Position.Y = 430.000000000000000000 14 | Size.Width = 368.000000000000000000 15 | Size.Height = 50.000000000000000000 16 | Size.PlatformDefault = False 17 | TabOrder = 1 18 | object Button1: TButton 19 | Align = Center 20 | Size.Width = 144.000000000000000000 21 | Size.Height = 36.000000000000000000 22 | Size.PlatformDefault = False 23 | TabOrder = 0 24 | Text = 'Get current state' 25 | OnClick = Button1Click 26 | end 27 | end 28 | object Memo1: TMemo 29 | Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] 30 | DataDetectorTypes = [] 31 | Align = Client 32 | Size.Width = 368.000000000000000000 33 | Size.Height = 430.000000000000000000 34 | Size.PlatformDefault = False 35 | TabOrder = 0 36 | Viewport.Width = 364.000000000000000000 37 | Viewport.Height = 426.000000000000000000 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /Samples/FFormCPP.h: -------------------------------------------------------------------------------- 1 | //--------------------------------------------------------------------------- 2 | 3 | #ifndef FFormCPPH 4 | #define FFormCPPH 5 | //--------------------------------------------------------------------------- 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "UNetworkState.hpp" 17 | //--------------------------------------------------------------------------- 18 | class TFormSample : public TForm 19 | { 20 | __published: // IDE-managed Components 21 | TLayout *Layout1; 22 | TButton *Button1; 23 | TMemo *Memo1; 24 | void __fastcall Button1Click(TObject *Sender); 25 | private: // User declarations 26 | TNetworkState *FNetworkState; 27 | 28 | protected: 29 | void __fastcall DoOnNetworkStateChanged(TObject* Sender, TNetworkStateValue Value); 30 | 31 | public: // User declarations 32 | __fastcall TFormSample(TComponent* Owner); 33 | }; 34 | //--------------------------------------------------------------------------- 35 | extern PACKAGE TFormSample *FormSample; 36 | //--------------------------------------------------------------------------- 37 | #endif 38 | -------------------------------------------------------------------------------- /Samples/Samples.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {D148EF59-0DAF-430B-8DAF-EFA870DE10C1} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Default.Personality.12 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /Samples/info.plist.TemplateiOS.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%VersionInfoPListKeys%> 6 | <%ExtraInfoPListKeys%> 7 | 8 | 9 | -------------------------------------------------------------------------------- /Samples/libReachability.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Code-Partners/firemonkey-network-state/da886176ca2aeca1d62f5977f889903cf2af79c5/Samples/libReachability.a -------------------------------------------------------------------------------- /Samples/libReachability64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Code-Partners/firemonkey-network-state/da886176ca2aeca1d62f5977f889903cf2af79c5/Samples/libReachability64.a -------------------------------------------------------------------------------- /Source/Android/BroadcastReceiver/UBroadcastReceiver.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit UBroadcastReceiver; 20 | 21 | interface 22 | 23 | {$IFDEF ANDROID} 24 | uses 25 | System.SysUtils, System.Classes, Androidapi.JNIBridge, Androidapi.JNI.Embarcadero, 26 | Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.JavaTypes, Androidapi.helpers; 27 | 28 | type 29 | // based on https://github.com/ashumkin/Delphi-Android-BroadcastSample 30 | 31 | TDataReceivedEvent = procedure (Sender: TObject; Data: string) of object; 32 | 33 | TBroadcastReceiver = class; 34 | 35 | TListener = class(TJavaLocal, JFMXBroadcastReceiverListener) 36 | private 37 | fOwner: TBroadcastReceiver; 38 | fReceiver: JFMXBroadcastReceiver; 39 | public 40 | constructor Create(aOwner: TBroadcastReceiver); 41 | destructor Destroy; override; 42 | procedure onReceive(context: JContext; intent: JIntent); cdecl; 43 | end; 44 | 45 | TOnReceive = procedure (aContext: JContext; aIntent: JIntent; aResultCode: integer) of object; 46 | 47 | TBroadcastReceiver = class (TComponent) 48 | private 49 | fListener : TListener; 50 | fRegistered: boolean; 51 | fOnReceive: TOnReceive; 52 | protected 53 | procedure DoReceiveBroadcast(AContext: JContext; AIntent: JIntent; AResultCode: integer); virtual; 54 | public 55 | constructor Create(AOwner: TComponent; aOnReceiveProc: TOnReceive); reintroduce; 56 | destructor Destroy; override; 57 | procedure AddActions(const Args: array of JString); 58 | end; 59 | {$ENDIF} 60 | 61 | implementation 62 | 63 | { TBroadcastReceiver } 64 | 65 | {$IFDEF ANDROID} 66 | constructor TBroadcastReceiver.Create(AOwner: TComponent; aOnReceiveProc: TOnReceive); 67 | begin 68 | inherited Create(AOwner); 69 | fListener := TListener.Create(Self); 70 | fOnReceive := aOnReceiveProc; 71 | end; 72 | 73 | destructor TBroadcastReceiver.Destroy; 74 | begin 75 | fListener.Free; 76 | inherited; 77 | end; 78 | 79 | procedure TBroadcastReceiver.AddActions(const Args: array of JString); 80 | var 81 | vFilter: JIntentFilter; 82 | i: Integer; 83 | begin 84 | if fRegistered then 85 | TAndroidHelper.context.getApplicationContext.UnregisterReceiver(fListener.fReceiver); 86 | 87 | vFilter := TJIntentFilter.JavaClass.init; 88 | for i := 0 to High(Args) do 89 | vFilter.addAction(Args[i]); 90 | 91 | TAndroidHelper.context.getApplicationContext.registerReceiver(fListener.fReceiver, vFilter); 92 | fRegistered := true; 93 | end; 94 | 95 | // 96 | 97 | procedure TBroadcastReceiver.DoReceiveBroadcast(AContext: JContext; AIntent: JIntent; AResultCode: integer); 98 | begin 99 | // 100 | end; 101 | 102 | { TListener } 103 | 104 | constructor TListener.Create(aOwner: TBroadcastReceiver); 105 | begin 106 | inherited Create; 107 | fOwner := aOwner; 108 | fReceiver := TJFMXBroadcastReceiver.JavaClass.init(Self); 109 | end; 110 | 111 | destructor TListener.Destroy; 112 | begin 113 | TAndroidHelper.context.getApplicationContext.unregisterReceiver(fReceiver); 114 | inherited; 115 | end; 116 | 117 | // usually android call it from "UI thread" - it's not main Delphi thread 118 | procedure TListener.onReceive(context: JContext; intent: JIntent); 119 | begin 120 | if Assigned(fOwner.fOnReceive) then 121 | fOwner.fOnReceive(Context, Intent, fReceiver.getResultCode); 122 | end; 123 | {$ENDIF} 124 | 125 | end. 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /Source/Android/BroadcastReceiver/UNetworkStateBroadcastReceiver.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit UNetworkStateBroadcastReceiver; 20 | 21 | interface 22 | 23 | {$IFDEF ANDROID} 24 | uses 25 | System.SysUtils, System.Classes, Androidapi.JNI.GraphicsContentViewText, 26 | Androidapi.helpers, UBroadcastReceiver, Androidapi.JNI.Net, Androidapi.JNI.OS, 27 | Androidapi.JNI.JavaTypes; 28 | 29 | type 30 | TNetworkStateBroadcastReceiver = class (TBroadcastReceiver) 31 | private 32 | FOnConnectivityAction: TNotifyEvent; 33 | protected 34 | procedure DoReceiveBroadcast(AContext: JContext; AIntent: JIntent; AResultCode: integer); override; 35 | public 36 | constructor Create( 37 | AOwner: TComponent; AOnConnectivityAction: TNotifyEvent 38 | ); reintroduce; 39 | end; 40 | {$ENDIF} 41 | 42 | implementation 43 | 44 | {$IFDEF ANDROID} 45 | const 46 | CONNECTIVITY_ACTION = 'android.net.conn.CONNECTIVITY_CHANGE'; 47 | 48 | { UNetworkStateBroadcastManager } 49 | 50 | constructor TNetworkStateBroadcastReceiver.Create( 51 | AOwner: TComponent; AOnConnectivityAction: TNotifyEvent 52 | ); 53 | begin 54 | inherited Create(AOwner, self.DoReceiveBroadcast); 55 | self.FOnConnectivityAction := AOnConnectivityAction; 56 | 57 | self.AddActions([ 58 | StringToJString(CONNECTIVITY_ACTION) 59 | ]); 60 | end; 61 | 62 | procedure TNetworkStateBroadcastReceiver.DoReceiveBroadcast(AContext: JContext; 63 | AIntent: JIntent; AResultCode: integer); 64 | var 65 | Action: string; 66 | begin 67 | inherited; 68 | 69 | Action := JStringToString(AIntent.getAction); 70 | 71 | if Action = CONNECTIVITY_ACTION then begin 72 | if(AIntent.getExtras() <> nil) then begin 73 | if Assigned(self.FOnConnectivityAction) then begin 74 | TThread.Synchronize( 75 | nil, 76 | procedure 77 | begin 78 | self.FOnConnectivityAction(self); 79 | end 80 | ); 81 | end; 82 | end; 83 | end; 84 | end; 85 | {$ENDIF} 86 | 87 | end. 88 | -------------------------------------------------------------------------------- /Source/Android/UNetworkState.Android.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit UNetworkState.Android; 20 | 21 | interface 22 | 23 | {$IFDEF ANDROID} 24 | uses 25 | System.SysUtils, System.Classes, UNetworkState, UNetworkStateBroadcastReceiver, 26 | Androidapi.JNIBridge, Androidapi.JNI.GraphicsContentViewText, 27 | Androidapi.JNI.JavaTypes, FMX.Helpers.Android, Androidapi.JNI.Net, 28 | Androidapi.Helpers; 29 | 30 | type 31 | TAndroidNetworkState = class (TNetworkState) 32 | private 33 | FBroadcastReceiver: TNetworkStateBroadcastReceiver; 34 | FConnectivityManager: JConnectivityManager; 35 | 36 | function GetConnectivityManager: JConnectivityManager; 37 | protected 38 | procedure DoOnConnectivityBroadcastAction(Sender: TObject); 39 | function GetCurrentValue: TNetworkStateValue; override; 40 | public 41 | constructor Create(AOwner: TComponent; 42 | AOnChange: TNetworkStateChangeEvent); reintroduce; override; 43 | end; 44 | {$ENDIF} 45 | 46 | implementation 47 | 48 | {$IFDEF ANDROID} 49 | 50 | { TAndroidNetworkState } 51 | 52 | constructor TAndroidNetworkState.Create(AOwner: TComponent; 53 | AOnChange: TNetworkStateChangeEvent); 54 | begin 55 | self.FConnectivityManager := self.GetConnectivityManager; 56 | 57 | self.FBroadcastReceiver := TNetworkStateBroadcastReceiver.Create( 58 | self, self.DoOnConnectivityBroadcastAction 59 | ); 60 | 61 | inherited; 62 | end; 63 | 64 | function TAndroidNetworkState.GetConnectivityManager: JConnectivityManager; 65 | var 66 | ConnectivityServiceNative: JObject; 67 | begin 68 | ConnectivityServiceNative := TAndroidHelper.Context.getSystemService( 69 | TJContext.JavaClass.CONNECTIVITY_SERVICE 70 | ); 71 | 72 | if not Assigned(ConnectivityServiceNative) then 73 | raise Exception.Create('Could not locate Connectivity Service'); 74 | 75 | Result := TJConnectivityManager.Wrap((ConnectivityServiceNative as ILocalObject).GetObjectID); 76 | 77 | if not Assigned(Result) then 78 | raise Exception.Create('Could not access Connectivity Manager'); 79 | end; 80 | 81 | procedure TAndroidNetworkState.DoOnConnectivityBroadcastAction(Sender: TObject); 82 | begin 83 | self.DoOnChange; 84 | end; 85 | 86 | function TAndroidNetworkState.GetCurrentValue: TNetworkStateValue; 87 | var 88 | ActiveNetwork: JNetworkInfo; 89 | Connected: boolean; 90 | begin 91 | ActiveNetwork := self.FConnectivityManager.getActiveNetworkInfo; 92 | 93 | Connected := Assigned(ActiveNetwork) and ActiveNetwork.isConnectedOrConnecting; 94 | 95 | if Connected then begin 96 | if ActiveNetwork.getType = TJConnectivityManager.JavaClass.TYPE_WIFI then 97 | Result := nsConnectedWifi 98 | else 99 | Result := nsConnectedMobileData; 100 | end 101 | else 102 | Result := nsDisconnected; 103 | end; 104 | 105 | {$ENDIF} 106 | 107 | end. 108 | -------------------------------------------------------------------------------- /Source/UNetworkState.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit UNetworkState; 20 | 21 | interface 22 | 23 | uses 24 | System.SysUtils, System.Classes; 25 | 26 | type 27 | TNetworkStateValue = (nsUnknown = 0, nsConnectedWifi = 1, nsConnectedMobileData = 2, nsDisconnected = 3); 28 | 29 | TNetworkStateChangeEvent = procedure (Sender: TObject; 30 | Value: TNetworkStateValue) of object; 31 | 32 | TNetworkState = class (TComponent) 33 | private 34 | FCurrentValue: TNetworkStateValue; 35 | FOnChange: TNetworkStateChangeEvent; 36 | protected 37 | procedure DoOnChange; 38 | function GetCurrentValue: TNetworkStateValue; virtual; 39 | 40 | constructor Create(AOwner: TComponent; 41 | AOnChange: TNetworkStateChangeEvent); reintroduce; virtual; 42 | public 43 | class function Factory( 44 | AOwner: TComponent; AOnChange: TNetworkStateChangeEvent 45 | ): TNetworkState; 46 | 47 | property CurrentValue: TNetworkStateValue read FCurrentValue; 48 | end; 49 | 50 | implementation 51 | 52 | uses 53 | {$IF DEFINED(Android)} 54 | UNetworkState.Android; 55 | {$ELSEIF DEFINED(iOS)} 56 | UNetworkState.iOS; 57 | {$IFEND} 58 | 59 | { TNetworkState } 60 | 61 | constructor TNetworkState.Create(AOwner: TComponent; 62 | AOnChange: TNetworkStateChangeEvent); 63 | begin 64 | inherited Create(AOwner); 65 | self.FOnChange := AOnChange; 66 | 67 | self.FCurrentValue := self.GetCurrentValue; 68 | end; 69 | 70 | class function TNetworkState.Factory(AOwner: TComponent; 71 | AOnChange: TNetworkStateChangeEvent): TNetworkState; 72 | begin 73 | {$IF DEFINED(Android)} 74 | Result := TAndroidNetworkState.Create(AOwner, AOnChange); 75 | {$ELSEIF DEFINED(iOS)} 76 | {$IF DEFINED(CPUARM)} // real device 77 | Result := TiOSNetworkState.Create(AOwner, AOnChange); 78 | {$ELSEIF DEFINED(CPUX86)} // simulator 79 | Result := TNetworkState.Create(AOwner, AOnChange); 80 | {$ENDIF} 81 | {$ENDIF} 82 | end; 83 | 84 | function TNetworkState.GetCurrentValue: TNetworkStateValue; 85 | begin 86 | Result := nsUnknown; 87 | end; 88 | 89 | procedure TNetworkState.DoOnChange; 90 | var 91 | NewValue: TNetworkStateValue; 92 | begin 93 | NewValue := self.GetCurrentValue; 94 | 95 | if (self.FCurrentValue <> NewValue) then begin 96 | self.FCurrentValue := NewValue; 97 | 98 | if Assigned(self.FOnChange) then 99 | self.FOnChange(self, self.FCurrentValue); 100 | end; 101 | end; 102 | 103 | end. 104 | -------------------------------------------------------------------------------- /Source/iOS/CaptiveNetwork.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit CaptiveNetwork; 20 | 21 | interface 22 | 23 | {$IFDEF IOS} 24 | uses 25 | Macapi.CoreFoundation; 26 | 27 | const 28 | libSystemConfiguration = '/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration'; 29 | 30 | function CNSetSupportedSSIDs(ssidArray: CFArrayRef): Boolean; cdecl; 31 | external libSystemConfiguration name _PU + 'CNSetSupportedSSIDs'; 32 | function CNMarkPortalOnline(interfaceName: CFStringRef): Boolean; cdecl; 33 | external libSystemConfiguration name _PU + 'CNMarkPortalOnline'; 34 | function CNMarkPortalOffline(interfaceName: CFStringRef): Boolean; cdecl; 35 | external libSystemConfiguration name _PU + 'CNMarkPortalOffline'; 36 | function CNCopySupportedInterfaces: CFArrayRef; cdecl; 37 | external libSystemConfiguration name _PU + 'CNCopySupportedInterfaces'; 38 | function CNCopyCurrentNetworkInfo(interfaceName: CFStringRef): CFDictionaryRef; cdecl; 39 | external libSystemConfiguration name _PU + 'CNCopyCurrentNetworkInfo'; 40 | {$ENDIF} 41 | 42 | implementation 43 | 44 | end. 45 | -------------------------------------------------------------------------------- /Source/iOS/SCNetworkReachability.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit SCNetworkReachability; 20 | 21 | interface 22 | 23 | {$IFDEF IOS} 24 | uses 25 | Macapi.CoreFoundation, Posix.SysSocket, Macapi.Dispatch; 26 | 27 | const 28 | libSystemConfiguration = '/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration'; 29 | // Stolen from Macapi.SystemConfiguration 30 | kSCNetworkFlagsConnectionAutomatic = 8; 31 | kSCNetworkFlagsConnectionRequired = 4; 32 | kSCNetworkFlagsInterventionRequired = 16; 33 | kSCNetworkFlagsIsDirect = 131072; 34 | kSCNetworkFlagsIsLocalAddress = 65536; 35 | kSCNetworkFlagsReachable = 2; 36 | kSCNetworkFlagsTransientConnection = 1; 37 | kSCNetworkReachabilityFlagsConnectionAutomatic = 8; 38 | kSCNetworkReachabilityFlagsConnectionOnDemand = 32; 39 | kSCNetworkReachabilityFlagsConnectionOnTraffic = 8; 40 | kSCNetworkReachabilityFlagsConnectionRequired = 4; 41 | kSCNetworkReachabilityFlagsInterventionRequired = 16; 42 | kSCNetworkReachabilityFlagsIsDirect = 131072; 43 | kSCNetworkReachabilityFlagsIsLocalAddress = 65536; 44 | kSCNetworkReachabilityFlagsReachable = 2; 45 | kSCNetworkReachabilityFlagsTransientConnection = 1; 46 | kSCNetworkReachabilityFlagsIsWWAN = $40000; // iOS only 47 | 48 | type 49 | SCNetworkReachabilityFlags = UInt32; 50 | 51 | SCNetworkReachabilityRef = ^__SCNetworkReachability; 52 | 53 | __SCNetworkReachability = record 54 | end; 55 | 56 | SCNetworkReachabilityContext = record 57 | version: CFIndex; 58 | info: Pointer; 59 | retain: function(info: Pointer): Pointer; 60 | release: procedure(info: Pointer); 61 | copyDescription: function(info: Pointer): CFStringRef; 62 | end; 63 | 64 | SCNetworkReachabilityContextPtr = ^SCNetworkReachabilityContext; 65 | 66 | SCNetworkReachabilityCallback = procedure(target: SCNetworkReachabilityRef; 67 | flags: SCNetworkReachabilityFlags; info: Pointer); 68 | 69 | function SCNetworkReachabilityCreateWithAddress(allocator: CFAllocatorRef; address: psockaddr): SCNetworkReachabilityRef; cdecl; 70 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityCreateWithAddress'; 71 | function SCNetworkReachabilityCreateWithAddressPair(allocator: CFAllocatorRef; localAddress: psockaddr; 72 | remoteAddress: psockaddr): SCNetworkReachabilityRef; cdecl; 73 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityCreateWithAddressPair'; 74 | function SCNetworkReachabilityCreateWithName(allocator: CFAllocatorRef; nodename: PChar): SCNetworkReachabilityRef; cdecl; 75 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityCreateWithName'; 76 | function SCNetworkReachabilityGetTypeID: CFTypeID; cdecl; 77 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityGetTypeID'; 78 | function SCNetworkReachabilityGetFlags(target: SCNetworkReachabilityRef; var flags: SCNetworkReachabilityFlags): Boolean; cdecl; 79 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityGetFlags'; 80 | function SCNetworkReachabilitySetCallback(target: SCNetworkReachabilityRef; callout: SCNetworkReachabilityCallback; 81 | var context: SCNetworkReachabilityContext): Boolean; cdecl; 82 | external libSystemConfiguration name _PU + 'SCNetworkReachabilitySetCallback'; 83 | function SCNetworkReachabilityScheduleWithRunLoop(target: SCNetworkReachabilityRef; runLoop: CFRunLoopRef; 84 | runLoopMode: CFStringRef): Boolean; cdecl; 85 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityScheduleWithRunLoop'; 86 | function SCNetworkReachabilityUnscheduleFromRunLoop(target: SCNetworkReachabilityRef; runLoop: CFRunLoopRef; runLoopMode: CFStringRef): Boolean; cdecl; 87 | external libSystemConfiguration name _PU + 'SCNetworkReachabilityUnscheduleFromRunLoop'; 88 | function SCNetworkReachabilitySetDispatchQueue(target: SCNetworkReachabilityRef; queue: dispatch_queue_t): Boolean; cdecl; 89 | external libSystemConfiguration name _PU + 'SCNetworkReachabilitySetDispatchQueue'; 90 | {$ENDIF} 91 | 92 | implementation 93 | 94 | end. 95 | -------------------------------------------------------------------------------- /Source/iOS/UNetworkState.iOS.pas: -------------------------------------------------------------------------------- 1 | {****************************************************} 2 | { } 3 | { firemonkey-network-state } 4 | { } 5 | { Copyright (C) 2018 Code Partners Pty Ltd } 6 | { } 7 | { http://www.code-partners.com } 8 | { } 9 | {****************************************************} 10 | { } 11 | { This Source Code Form is subject to the terms of } 12 | { the Mozilla Public License, v. 2.0. If a copy of } 13 | { the MPL was not distributed with this file, You } 14 | { can obtain one at } 15 | { } 16 | { http://mozilla.org/MPL/2.0/ } 17 | { } 18 | {****************************************************} 19 | unit UNetworkState.iOS; 20 | 21 | interface 22 | 23 | {$IFDEF IOS} 24 | uses 25 | System.SysUtils, System.Classes, UNetworkState, Macapi.ObjectiveC, 26 | Macapi.CoreFoundation, iOSApi.CocoaTypes, iOSApi.Foundation, 27 | Macapi.ObjCRuntime, Macapi.Helpers 28 | // linker will fail without these two files 29 | , SCNetworkReachability, CaptiveNetwork; 30 | 31 | type 32 | SCNetworkReachabilityFlags = UInt32; 33 | 34 | TReachability = class; 35 | 36 | Reachability = interface(NSObject) 37 | ['{B405394F-57B1-4FF1-83D9-8FBFA38FFD7B}'] 38 | function startNotifier: LongBool; cdecl; 39 | procedure stopNotifier; cdecl; 40 | function isReachable: LongBool; cdecl; 41 | function isReachableViaWWAN: LongBool; cdecl; 42 | function isReachableViaWiFi: LongBool; cdecl; 43 | function isConnectionRequired: LongBool; cdecl; 44 | function connectionRequired: LongBool; cdecl; 45 | function isConnectionOnDemand: LongBool; cdecl; 46 | function isInterventionRequired: LongBool; cdecl; 47 | function currentReachabilityStatus: NSInteger; cdecl; 48 | function reachabilityFlags: SCNetworkReachabilityFlags; cdecl; 49 | function currentReachabilityString: NSString; cdecl; 50 | function currentReachabilityFlags: NSString; cdecl; 51 | end; 52 | 53 | ReachabilityClass = interface(NSObjectClass) 54 | ['{39EC0490-2787-4BB9-95EA-77BB885BFD01}'] 55 | function reachabilityWithHostname(hostname: NSString): pointer; cdecl; 56 | function reachabilityForInternetConnection: pointer; cdecl; 57 | function reachabilityWithAddress: pointer; cdecl; 58 | function reachabilityForLocalWiFi: pointer; cdecl; 59 | end; 60 | 61 | TReachability = class(TOCGenericImport) 62 | end; 63 | 64 | INetworkChangeDelegate = interface(IObjectiveC) 65 | ['{BC4EABBE-F21F-4592-93B0-0C40415E4A91}'] 66 | procedure handleNetworkChange(notice: NSNotification); cdecl; 67 | end; 68 | 69 | TiOSNetworkState = class; 70 | 71 | TNetworkChangeDelegate = class (TOCLocal, INetworkChangeDelegate) 72 | private 73 | FNetworkState: TiOSNetworkState; 74 | public 75 | constructor Create(ANetworkState: TiOSNetworkState); 76 | 77 | // (void) handleNetworkChange:(NSNotification *)notice 78 | procedure handleNetworkChange(notice: NSNotification); cdecl; 79 | end; 80 | 81 | TiOSNetworkState = class (TNetworkState) 82 | private 83 | FReachability: Reachability; 84 | FDelegate: TNetworkChangeDelegate; 85 | protected 86 | function GetCurrentValue: TNetworkStateValue; override; 87 | public 88 | constructor Create(AOwner: TComponent; 89 | AOnChange: TNetworkStateChangeEvent); reintroduce; override; 90 | end; 91 | 92 | {$IFDEF CPUARM} 93 | {$IF DEFINED(IOS32)} 94 | function FakeLoader: Reachability; cdecl; external 'libReachability.a' name 'OBJC_CLASS_$_Reachability'; 95 | {$ELSEIF DEFINED(IOS64)} 96 | function FakeLoader: Reachability; cdecl; external 'libReachability64.a' name 'OBJC_CLASS_$_Reachability'; 97 | {$ENDIF} 98 | {$ENDIF} 99 | 100 | {$ENDIF} 101 | 102 | implementation 103 | 104 | {$IFDEF IOS} 105 | 106 | { TiOSNetworkState } 107 | 108 | constructor TiOSNetworkState.Create(AOwner: TComponent; 109 | AOnChange: TNetworkStateChangeEvent); 110 | begin 111 | FDelegate := TNetworkChangeDelegate.Create(self); 112 | 113 | TNSNotificationCenter.Wrap(TNSNotificationCenter.OCClass.defaultCenter).addObserver( 114 | FDelegate.GetObjectID, 115 | sel_getUid('handleNetworkChange:'), 116 | StringToID('kReachabilityChangedNotification'), 117 | nil 118 | ); 119 | 120 | FReachability := TReachability.Wrap(TReachability.OCClass.reachabilityForInternetConnection); 121 | FReachability.startNotifier; 122 | 123 | inherited; 124 | end; 125 | 126 | function TiOSNetworkState.GetCurrentValue: TNetworkStateValue; 127 | var 128 | Status: integer; 129 | begin 130 | Status := self.FReachability.currentReachabilityStatus; 131 | 132 | // 0 - disconnected, 1 - reachable via wifi, 2 - reachable via wwan 133 | if (Status = 0) then 134 | Result := nsDisconnected 135 | else if (Status = 2) then 136 | Result := nsConnectedWifi 137 | else 138 | Result := nsConnectedMobileData; 139 | end; 140 | 141 | { TNetworkChangeDelegate } 142 | 143 | constructor TNetworkChangeDelegate.Create(ANetworkState: TiOSNetworkState); 144 | begin 145 | inherited Create; 146 | self.FNetworkState := ANetworkState; 147 | end; 148 | 149 | procedure TNetworkChangeDelegate.handleNetworkChange(notice: NSNotification); 150 | begin 151 | TThread.Synchronize( 152 | nil, 153 | procedure 154 | begin 155 | self.FNetworkState.DoOnChange; 156 | end 157 | ); 158 | end; 159 | 160 | {$ENDIF} 161 | 162 | initialization 163 | 164 | end. 165 | --------------------------------------------------------------------------------