GithubHelp home page GithubHelp logo

loup-v / beacons Goto Github PK

View Code? Open in Web Editor NEW
78.0 6.0 53.0 275 KB

Flutter beacons plugin for Android and iOS.

License: Apache License 2.0

Kotlin 29.33% Ruby 2.49% Swift 32.45% Objective-C 0.31% Dart 35.41%
flutter geolocation location beacon beacons flutter-plugin ibeacon ibeacons altbeacon

beacons's Introduction

Beacons

pub package

Flutter plugin to work with beacons.
Supports Android API 16+ and iOS 8+.

Features:

  • Automatic permission management
  • Ranging
  • Monitoring (including background)

Supported beacons specifications:

  • iBeacon (iOS & Android)
  • Altbeacon (Android)

Installation

Add to pubspec.yaml:

dependencies:
  beacons: ^0.3.0

Note: The plugin is written in Swift for iOS.
There is a known issue for integrating swift plugin into Flutter project using the Objective-C template. Follow the instructions from Flutter#16049 to resolve the issue (Cocoapods 1.5+ is mandatory).

Setup specific for Android

Create a subclass of FlutterApplication:

class App : FlutterApplication() {

    override fun onCreate() {
        super.onCreate()

        // Beacons setup for Android
        BeaconsPlugin.init(this, object : BeaconsPlugin.BackgroundMonitoringCallback {
            override fun onBackgroundMonitoringEvent(event: BackgroundMonitoringEvent): Boolean {
                val intent = Intent(this@App, MainActivity::class.java)
                startActivity(intent)
                return true
            }
        })
    }
}

And register it in android/app/src/main/AndroidManifest.xml:

<manifest ...>
  ...
  <application
    android:name=".App"
    android:label="beacons_example"
    android:icon="@mipmap/ic_launcher">
    ...
  </application>
</manifest>

BeaconsPlugin.BackgroundMonitoringCallback is required to react to background monitoring events. The callback will be executed when a monitoring event is detected while the app is running in background. In the snipped above, it will start the Flutter app. It will also allow to receive a callback on the Flutter side. See background monitoring section for more details.

For permission, see below.

Setup specific for iOS

Nothing. Contrary to the general opinion, you do not need to enable any background mode.

For permission, see below.

Permission

In order to use beacons related features, apps are required to ask the location permission. It's a two step process:

  1. Declare the permission the app requires in configuration files
  2. Request the permission to the user when app is running (the plugin can handle this automatically)

For iOS

There are two available permissions in iOS: when in use and always.
The latter is required for background monitoring.

For more details about what you can do with each permission, see:
https://developer.apple.com/documentation/corelocation/choosing_the_authorization_level_for_location_services

Permission must be declared in ios/Runner/Info.plist:

<dict>
  <!-- When in use -->
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>Reason why app needs location</string>

  <!-- Always -->
  <!-- for iOS 11 + -->
  <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
  <string>Reason why app needs location</string>
  <!-- for iOS 9/10 -->
  <key>NSLocationAlwaysUsageDescription</key>
  <string>Reason why app needs location</string>
  ...
</dict>

For Android

There are two available permissions in Android: coarse and fine.
For beacons related features, there are no difference between the two permission.

Permission must be declared in android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <!-- or -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

How-to

Ranging and monitoring APIs are designed as reactive streams.

  • The first subscription to the stream will start the ranging/monitoring ;
  • The last cancelling (when there are no more subscription) on the stream will stop the ranging/monitoring operation.

Ranging beacons

Beacons.ranging(
  region: new BeaconRegionIBeacon(
    identifier: 'test',
    proximityUUID: '7da11b71-6f6a-4b6d-81c0-8abd031e6113',
  ),
  inBackground: false, // continue the ranging operation in background or not, see below
).listen((result) {
  // result contains a list of beacons
  // list can be empty if no matching beacons were found in range
}

Background ranging

When turned off, ranging will automatically pause when app goes to background and resume when app comes back to foreground. Otherwise it will actively continue in background until the app is terminated by the OS.

Ranging beacons while the app is terminated is not supported by the OS. For this kind of usage, see background monitoring.

Monitoring beacons

Beacons.monitoring(
  region: new BeaconRegionIBeacon(
    identifier: 'test',
    proximityUUID: '7da11b71-6f6a-4b6d-81c0-8abd031e6113',
  ),
  inBackground: false, // continue the monitoring operation in background or not, see below
).listen((result) {
  // result contains the new monitoring state:
  // - enter
  // - exit
}

Background monitoring

When turned off, monitoring will automatically pause when app goes to background and resume when app comes back to foreground. Otherwise it will actively continue in background until the app is terminated by the OS.

Once the app has been terminated, the monitoring will continue.
If a monitoring event happens, the OS will start the app in background for several seconds (nothing will be visible for the user). The OS is providing you the opportunity to perform some quick operation, like showing a local notification.

In order to listen to background monitoring events, you can subscribe to a special stream. This stream is passive: it does not start a monitoring operation. You are still required to start it using Beacons.monitoring(inBackground: true).

Because the OS will run the app in background for several seconds only, before terminating it again, the good place to setup the listener is during app startup.

class MyApp extends StatefulWidget {
  MyApp() {
    Beacons.backgroundMonitoringEvents().listen((event) {
      final BackgroundMonitoringEventType type = event.type // didEnterRegion, didExitRegion or didDetermineState
      final BeaconRegion region = event.region // The monitored region associated to the event
      final MonitoringState state = event.state // useful for type = didDetermineState

      // do something quick here to react to the background monitoring event, like showing a notification
    });
  }

  @override
  _MyAppState createState() => new _MyAppState();
}

For testing background monitoring and what result you should expect, read:
https://developer.radiusnetworks.com/2013/11/13/ibeacon-monitoring-in-the-background-and-foreground.html

Alternatively to starting/stoping monitoring using Beacons.monitoring() stream subscription, you can use the following imperative API:

// Result will be successful if monitoring has started, or contain the reason why it has not (permission denied, etc)
final BeaconsResult result = await Beacons.startMonitoring(
  region: BeaconRegionIBeacon(
    identifier: 'test',
    proximityUUID: 'uuid',
  ),
  inBackground: true,
);

await Beacons.stopMonitoring(
  region: BeaconRegionIBeacon(
    identifier: 'test',
    proximityUUID: 'uuid',
  ),
);

Note that these functions can only start/stop the monitoring.
To receive the associated monitoring events, listen to the stream from Beacons.backgroundMonitoringEvents().

Beacons types

For every API that requires or return a region or a beacon, you can work with the different types of beacons specs.

Regardless of the beacons specs, each region requires an unique identifier that are used by the engine under the hood to uniquely identify and manage a ranging/monitoring request.

Generic

Beacons.ranging(region: BeaconRegion(
    identifier: 'test',
    ids: ['id1', 'id2', 'id3'],
  ),
).listen((result) {
  final Beacon beacon = result.beacons.first;
});

iBeacon

Beacons.ranging(region: BeaconRegionIBeacon(
    identifier: 'test',
    proximityUUID: 'some-uuid',
    major:0,
    minor: 0,
  ),
).listen((result) {
  final BeaconIBeacon beacon = BeaconIBeacon.from(result.beacons.first);
});

Under the hood

  • iOS uses native iOS CoreLocation
  • Android uses the third-party library android-beacon-library (Apache License 2.0)

Each technology has its own specificities.
The plugin does its best to abstract it and expose a common logic, but for an advanced usage, you would probably still need to familiarize yourself with the native technology.

Sponsor

Beacons plugin development is sponsored by Pointz, a startup that rewards people for spending time at local, brick and mortar businesses. Pointz is proudly based in Birmingham, AL.

Author

Beacons plugin is developed by Loup, a mobile development studio based in Montreal and Paris.
You can contact us at [email protected]

License

Apache License 2.0

beacons's People

Contributors

lukaspili avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

beacons's Issues

Need help (informations)! :)

Hello,

can you help me and explain me with a little words what exaclty is this package ? Is an app or is a plugin that I can use in my app ?

I have some beacons devices and I'm trying to create an app that get notifications from beacons. Is this possible and how ?

Thankyou very much!

Start Tracking is crashing the example application

E/AndroidRuntime(32216): FATAL EXCEPTION: IntentService[BeaconIntentProcessor]
E/AndroidRuntime(32216): Process: io.intheloup.beaconsexample, PID: 32216
E/AndroidRuntime(32216): java.lang.RuntimeException: Methods marked with @UiThread must be executed on the main thread. Current thread: IntentService[BeaconIntentProcessor]
E/AndroidRuntime(32216): at io.flutter.embedding.engine.FlutterJNI.ensureRunningOnMainThread(FlutterJNI.java:795)
E/AndroidRuntime(32216): at io.flutter.embedding.engine.FlutterJNI.dispatchPlatformMessage(FlutterJNI.java:685)
E/AndroidRuntime(32216): at io.flutter.embedding.engine.dart.DartMessenger.send(DartMessenger.java:80)
E/AndroidRuntime(32216): at io.flutter.embedding.engine.dart.DartExecutor.send(DartExecutor.java:168)
E/AndroidRuntime(32216): at io.flutter.view.FlutterNativeView.send(FlutterNativeView.java:117)
E/AndroidRuntime(32216): at io.intheloup.streamschannel.StreamsChannel$IncomingStreamRequestHandler$EventSinkImplementation.success(StreamsChannel.java:153)
E/AndroidRuntime(32216): at io.intheloup.beacons.channel.Channels$Handler$onListen$1.invoke(Channels.kt:88)
E/AndroidRuntime(32216): at io.intheloup.beacons.channel.Channels$Handler$onListen$1.invoke(Channels.kt:80)
E/AndroidRuntime(32216): at io.intheloup.beacons.logic.BeaconsClient.didRangeBeaconsInRegion(BeaconsClient.kt:218)
E/AndroidRuntime(32216): at org.altbeacon.beacon.IntentHandler.convertIntentsToCallbacks(IntentHandler.java:49)
E/AndroidRuntime(32216): at org.altbeacon.beacon.BeaconIntentProcessor.onHandleIntent(BeaconIntentProcessor.java:61)
E/AndroidRuntime(32216): at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
E/AndroidRuntime(32216): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(32216): at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime(32216): at android.os.HandlerThread.run(HandlerThread.java:61)
I/AndroidRuntime(32216): To Report FATAL to activityManagerService
D/beacons monitoring(32216): detach foreground notifier
D/beacons client(32216): stop Ranging (inBackground:false) for region: test
I/BeaconService(32216): stop ranging received
I/AndroidRuntime(32216): Finished reporting FATAL to activityManagerService
I/Process (32216): Sending signal. PID: 32216 SIG: 9
Lost connection to device.
I/Kernel (32216): [16622.359851]Mali<2>:
I/Kernel (32216): Session has ended
I/Kernel (32216): [16622.359910] (3)[32434:SendFrameDataTa][ION]warning: release handle @ client destory: handle=d1300bc0, buf=ddbf0d80, ref=7, size=2359296, kmap=0

App crashes when checking permissions

App crashes when Beacons.checkStatus is called only when Location Permission is set to "when in use" on device.

Beacons.checkStatus(permission: new LocationPermission(ios: LocationPermissionIOS.always));

When Location Permission is set to "Always" or "Never" the call works fine.

How to stop ranging?

Hi,

I could not find a method to call to stop ranging beacons. There's a stopMonitoring method. Could anyone kindly tell me how to programmatically stop ranging beacons after calling Beacons.ranging().

Thanks,

Wishlist: Remove Kotlin Dependency

We don't use Kotlin so removing this unnecessary dependency would decrease package size and project complexity. For libraries we prefer to stock with pure java.

Trouble integrating Swift plugin

Couldn't integrate plugin into my Flutter project. I believe the problem has to do with the note mentioned in the readme.

After adding the package to .yaml...

First error:

The “Swift Language Version” (SWIFT_VERSION) build setting must be set to a supported value for targets which use Swift...

Then, I added the following to Podfile...

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['SWIFT_VERSION'] = '3.2'
    end
  end
end

Next error:

/Users/andrew/dev/Pointz/Frontend/ios/Pods/Headers/Public/beacons/BeaconsPlugin.h:1:9: error: 'Flutter/Flutter.h' file not found
    #import <Flutter/Flutter.h>

Then, I added the following to Podfile...

use_frameworks!

and

pre_install do |installer|
 Pod::Installer::Xcode::TargetValidator.send(:define_method,:verify_no_static_framework_transitive_dependencies) {}
end

and

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.headers_build_phase.files.each do |file|
      file.settings = { 'ATTRIBUTES' => ['Public'] }
    end
  end
end

and then, I deleted Podfile.lock, /ios/Pods and ran flutter clean and got the following error:

Warning: Multiple build commands for output file /Users/andrew/dev/Pointz/Frontend/build/ios/Debug-iphoneos/BoringSSL/openssl.framework/Headers/x509.h
    Warning: Multiple build commands for output file /Users/andrew/dev/Pointz/Frontend/build/ios/Debug-iphoneos/BoringSSL/openssl.framework/Headers/x509_vfy.h
    Warning: Multiple build commands for output file /Users/andrew/dev/Pointz/Frontend/build/ios/Debug-iphoneos/BoringSSL/openssl.framework/Headers/x509v3.h
    In file included from /Users/andrew/dev/Pointz/Frontend/ios/Pods/GoogleToolboxForMac/Foundation/GTMLogger.m:19:
    /Users/andrew/dev/Pointz/Frontend/ios/Pods/GoogleToolboxForMac/Foundation/GTMLogger.h:53:9: fatal error: 'GTMDefines.h' file not found
    #import "GTMDefines.h"
            ^~~~~~~~~~~~~~
    1 error generated.
Could not build the precompiled application for the device.

I've tried a bunch of other stuff as well, but no dice.

Here's my flutter doctor -v output:

[✓] Flutter (Channel master, v0.4.5-pre.55, on Mac OS X 10.12.6 16G1212, locale en-US)
    • Flutter version 0.4.5-pre.55 at /Users/Andrew/dev/flutter
    • Framework revision be6501a91c (9 hours ago), 2018-05-21 11:54:38 +0100
    • Engine revision 1179c38a42
    • Dart version 2.0.0-dev.55.0.flutter-43635d3372

[✓] iOS toolchain - develop for iOS devices (Xcode 9.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 9.1, Build version 9B55
    • ios-deploy 1.9.2
    • CocoaPods version 1.5.0

[✓] Android Studio (version 2.3)
    • Android Studio at /Applications/Android Studio 2.app/Contents
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

Beacons.startMonitoring is crashing the app

When I try to use the method Beacons.startMonitoring withouth starting a .monitor listener or stream (but set the backgroundMonitoringEvents method), the app crashes with the following error.

I/flutter (30714): beacons: invoke beacons->startMonitoring {"region":{"identifier":"test","ids":["b65de587b6494010af5bb6a733fc8ddd"],"bluetoothAddress":null},"permission":"coarse","inBackground":true}
D/beacons client(30714): start Monitoring (inBackground:true) for region: test
I/zygote64(30714): Do partial code cache collection, code=118KB, data=70KB
I/zygote64(30714): After code cache collection, code=118KB, data=70KB
I/zygote64(30714): Increasing code cache capacity to 512KB
E/AndroidRuntime(30714): FATAL EXCEPTION: main
E/AndroidRuntime(30714): Process: com.anxaneta.motobeacon, PID: 30714
E/AndroidRuntime(30714): kotlin.KotlinNullPointerException
E/AndroidRuntime(30714): at io.intheloup.beacons.data.RegionModel.getFrameworkValue(RegionModel.kt:17)
E/AndroidRuntime(30714): at io.intheloup.beacons.logic.SharedMonitor.start(SharedMonitor.kt:58)
E/AndroidRuntime(30714): at io.intheloup.beacons.logic.BeaconsClient.startRequest(BeaconsClient.kt:188)
E/AndroidRuntime(30714): at io.intheloup.beacons.logic.BeaconsClient.startMonitoring(BeaconsClient.kt:146)
E/AndroidRuntime(30714): at io.intheloup.beacons.channel.Channels$startMonitoring$1.doResume(Channels.kt:65)
E/AndroidRuntime(30714): at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:42)
E/AndroidRuntime(30714): at kotlinx.coroutines.experimental.DispatchedTask$DefaultImpls.run(Dispatched.kt:161)
E/AndroidRuntime(30714): at kotlinx.coroutines.experimental.DispatchedContinuation.run(Dispatched.kt:25)
E/AndroidRuntime(30714): at android.os.Handler.handleCallback(Handler.java:790)
E/AndroidRuntime(30714): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(30714): at android.os.Looper.loop(Looper.java:164)
E/AndroidRuntime(30714): at android.app.ActivityThread.main(ActivityThread.java:6499)
E/AndroidRuntime(30714): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(30714): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
E/AndroidRuntime(30714): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
I/Process (30714): Sending signal. PID: 30714 SIG: 9
Lost connection to device.

Error: Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.content.LocalBroadcastManager"

E/AndroidRuntime(25157): FATAL EXCEPTION: main
E/AndroidRuntime(25157): Process: com.flutterbeaconexample, PID: 25157
E/AndroidRuntime(25157): java.lang.NoClassDefFoundError: Failed resolution of: Landroid/support/v4/content/LocalBroadcastManager;
E/AndroidRuntime(25157): at org.altbeacon.beacon.BeaconLocalBroadcastProcessor.unregister(BeaconLocalBroadcastProcessor.java:82)
E/AndroidRuntime(25157): at org.altbeacon.beacon.BeaconLocalBroadcastProcessor.register(BeaconLocalBroadcastProcessor.java:74)
E/AndroidRuntime(25157): at org.altbeacon.beacon.service.BeaconService.ensureNotificationProcessorSetup(BeaconService.java:257)
E/AndroidRuntime(25157): at org.altbeacon.beacon.service.BeaconService.onCreate(BeaconService.java:219)
E/AndroidRuntime(25157): at android.app.ActivityThread.handleCreateService(ActivityThread.java:3534)
E/AndroidRuntime(25157): at android.app.ActivityThread.-wrap6(ActivityThread.java)
E/AndroidRuntime(25157): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1732)
E/AndroidRuntime(25157): at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(25157): at android.os.Looper.loop(Looper.java:154)
E/AndroidRuntime(25157): at android.app.ActivityThread.main(ActivityThread.java:6776)
E/AndroidRuntime(25157): at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(25157): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
E/AndroidRuntime(25157): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
E/AndroidRuntime(25157): Caused by: java.lang.ClassNotFoundException: Didn't find class "android.support.v4.content.LocalBroadcastManager" on path: DexPathList[[zip file "/data/app/com.flutterbeaconexample-2/base.apk"],nativeLibraryDirectories=[/data/app/com.flutterbeaconexample-2/lib/arm, /data/app/com.flutterbeaconexample-2/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
E/AndroidRuntime(25157): at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
E/AndroidRuntime(25157): at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
E/AndroidRuntime(25157): at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
E/AndroidRuntime(25157): ... 13 more
Lost connection to device.

monitoring stopped working on IOS

Hi,

I'm using the latest of the lib.
Background monitoring is working fine on Android but not on IOS.
I'm pretty sure it worked at some point on IOS, thus I guess it's due to an update on IOS in 2019.

Ranging is working in foreground on IOS.
I use this as a work around but definitely does cover all my needs for my app

I tried the sample app (https://pub.dartlang.org/packages/beacons#-example-tab-) same, monitoring does not work on IOS.

any idea?

I guess the issue is somewhere in the swift code, any code I can have a look at to try to fix this?

cheers

Error: The argument type 'String' can't be assigned to the parameter type 'DiagnosticsNode'.

hello
I am trying to run the app on IOS, but it keeps showing me the following error in the console:


Xcode's output:
↳
    === BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Debug ===

    Compiler message:
    file:///development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.3.0/lib/channel/helper.dart:18:56: Error: The argument type 'String' can't be assigned to the parameter type 'DiagnosticsNode'.
     - 'DiagnosticsNode' is from 'package:flutter/src/foundation/diagnostics.dart' ('file:///development/flutter/packages/flutter/lib/src/foundation/diagnostics.dart').
    Try changing the type of the parameter, or casting the argument to 'DiagnosticsNode'.
          context: 'while invoking ${channel.name}/$method',
                                                           ^

Restart monitoring after reboot

Thanks for this great library.
I'd like to know if there is a solution on starting the background monitoring service even when the phone gets restarted.

java.lang.IllegalArgumentException: Unsupported value: Result(isSuccessful=true, region=null, data=true, error=null)

When we try to use requestPermission function the Android app crashes with the following error log. iOS works just fine.

await Beacons.requestPermission(
  new LocationPermission(
    ios: LocationPermissionIOS.always, 
    android: LocationPermissionAndroid.fine
 )
);

E/AndroidRuntime: FATAL EXCEPTION: main Process: at.pluscity.PlusCity, PID: 7565 java.lang.IllegalArgumentException: Unsupported value: Result(isSuccessful=true, region=null, data=true, error=null) at io.flutter.plugin.common.StandardMessageCodec.writeValue(StandardMessageCodec.java:293) at io.flutter.plugin.common.StandardMethodCodec.encodeSuccessEnvelope(StandardMethodCodec.java:57) at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler$1.success(MethodChannel.java:194) at io.intheloup.beacons.channel.Channels$requestPermission$1.doResume(Channels.kt:54) at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:42) at kotlinx.coroutines.experimental.DispatchedTask$DefaultImpls.run(Dispatched.kt:161) at kotlinx.coroutines.experimental.DispatchedContinuation.run(Dispatched.kt:25) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:6934) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

java.lang.IllegalArgumentException: Service not registered

When using the flutter plugin barcode_scan our Android app crashes when closing the barcode scanner activity.

E/AndroidRuntime(12011): java.lang.RuntimeException: Unable to destroy activity {at.pluscity.PlusCity/com.apptreesoftware.barcodescan.BarcodeScannerActivity}: java.lang.IllegalArgumentException: Service not registered: org.altbeacon.beacon.BeaconManager$BeaconServiceConnection@2036956e E/AndroidRuntime(12011): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4891) E/AndroidRuntime(12011): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4909) E/AndroidRuntime(12011): at android.app.ActivityThread.access$1600(ActivityThread.java:218) E/AndroidRuntime(12011): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1788) E/AndroidRuntime(12011): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime(12011): at android.os.Looper.loop(Looper.java:145) E/AndroidRuntime(12011): at android.app.ActivityThread.main(ActivityThread.java:6934) E/AndroidRuntime(12011): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(12011): at java.lang.reflect.Method.invoke(Method.java:372) E/AndroidRuntime(12011): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) E/AndroidRuntime(12011): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199) E/AndroidRuntime(12011): Caused by: java.lang.IllegalArgumentException: Service not registered: org.altbeacon.beacon.BeaconManager$BeaconServiceConnection@2036956e E/AndroidRuntime(12011): at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:1141) E/AndroidRuntime(12011): at android.app.ContextImpl.unbindService(ContextImpl.java:2254) E/AndroidRuntime(12011): at android.content.ContextWrapper.unbindService(ContextWrapper.java:572) E/AndroidRuntime(12011): at io.intheloup.beacons.logic.BeaconsClient.unbindService(BeaconsClient.kt:246) E/AndroidRuntime(12011): at org.altbeacon.beacon.BeaconManager.unbind(BeaconManager.java:453) E/AndroidRuntime(12011): at io.intheloup.beacons.logic.BeaconsClient.unbind(BeaconsClient.kt:61) E/AndroidRuntime(12011): at io.intheloup.beacons.BeaconsPlugin$1.onActivityDestroyed(BeaconsPlugin.kt:35) E/AndroidRuntime(12011): at android.app.Application.dispatchActivityDestroyed(Application.java:269) E/AndroidRuntime(12011): at android.app.Activity.onDestroy(Activity.java:1861) E/AndroidRuntime(12011): at android.app.Activity.performDestroy(Activity.java:6843) E/AndroidRuntime(12011): at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1169) E/AndroidRuntime(12011): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4869) E/AndroidRuntime(12011): ... 10 more

type 'String' is not a subtype of type 'int' - Error thrown when Major set on iBeacon selection

Hey there,

I've got my beacon detected with Generic UUID, Major and Minor settings in place. With iBeacon, it seems when I have any value (String, int, etc.) in the Major text area, this error is thrown. I am able to use iBeacon when Major is blank.

Stacktrace:

` ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
I/flutter (17107): The following assertion was thrown while handling a gesture:
I/flutter (17107): type 'String' is not a subtype of type 'int'

When the exception was thrown, this was the stack:
I/flutter (17107): #0 new BeaconRegionIBeacon.from (file:///D:/Projects/flutter_beacons/beacons/lib/data/beacon_region.dart)
I/flutter (17107): #1 _HeaderState._onTapSubmit (file:///D:/Projects/flutter_beacons/beacons/example/lib/header.dart:84:40)
I/flutter (17107): #2 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
I/flutter (17107): #3 TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:161:9)
I/flutter (17107): #4 TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:94:7)
I/flutter (17107): #5 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:315:9)
I/flutter (17107): #6 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
I/flutter (17107): #7 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
I/flutter (17107): #8 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:143:19)
I/flutter (17107): #9 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
I/flutter (17107): #10 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
I/flutter (17107): #11 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
I/flutter (17107): #12 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
I/flutter (17107): #13 _invoke1 (dart:ui/hooks.dart:134:13)
I/flutter (17107): #14 _dispatchPointerDataPacket (dart:ui/hooks.dart:91:5)
I/flutter (17107):
I/flutter (17107): Handler: onTap
I/flutter (17107): Recognizer:
I/flutter (17107): TapGestureRecognizer#fc434(debugOwner: GestureDetector, state: possible, won arena, finalPosition:
I/flutter (17107): Offset(199.4, 276.3), sent tap down)
I/flutter (17107): ════════════════════════════════════════════════════════════════════════════════════════════════════`

I'm still learning both Flutter and Dart, and tried to see if there were any mismatched variables, but saw none. This is not an issue for me as I am able to work around it, just figured I would make an issue in case it's something needing fixed.

This error was produced on a Google Pixel running the Android P Beta.

Android crashes when monitoring background events

Tested with the example project.

When an enter event is triggered while the app is in the background (still running, not terminated) the app crashes with the following error in the console

E/flutter ( 2680): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 2680): 'file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart': Failed assertion: line 161 pos 16: 'false': cannot parse json to MonitoringState: enter
E/flutter ( 2680): #0      _AssertionError._doThrowNew (dart:core/runtime/liberrors_patch.dart:37:39)
E/flutter ( 2680): #1      _AssertionError._throwNew (dart:core/runtime/liberrors_patch.dart:33:5)
E/flutter ( 2680): #2      _JsonCodec.monitoringStateFromJson (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart)
E/flutter ( 2680): #3      _JsonCodec.monitoringResultFromJson (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart:96:32)
E/flutter ( 2680): #4      _Codec.decodeMonitoringResult (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart:14:18)
E/flutter ( 2680): #5      _Channels.monitoring.<anonymous closure> (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/channel.dart:54:21)
E/flutter ( 2680): #6      _MapStream._handleData (dart:async/stream_pipe.dart:227:21)
E/flutter ( 2680): #7      _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
E/flutter ( 2680): #8      _RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10)
E/flutter ( 2680): #9      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330:11)
E/flutter ( 2680): #10     _DelayedData.perform (dart:async/stream_impl.dart:578:14)
E/flutter ( 2680): #11     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694:11)
E/flutter ( 2680): #12     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654:7)
E/flutter ( 2680): #13     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter ( 2680): #14     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter ( 2680): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter ( 2680): 'file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart': Failed assertion: line 161 pos 16: 'false': cannot parse json to MonitoringState: enter
E/flutter ( 2680): #0      _AssertionError._doThrowNew (dart:core/runtime/liberrors_patch.dart:37:39)
E/flutter ( 2680): #1      _AssertionError._throwNew (dart:core/runtime/liberrors_patch.dart:33:5)
E/flutter ( 2680): #2      _JsonCodec.monitoringStateFromJson (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart)
E/flutter ( 2680): #3      _JsonCodec.monitoringResultFromJson (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart:96:32)
E/flutter ( 2680): #4      _Codec.decodeMonitoringResult (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/codec.dart:14:18)
E/flutter ( 2680): #5      _Channels.monitoring.<anonymous closure> (file:///Users/alfuller/development/flutter/.pub-cache/hosted/pub.dartlang.org/beacons-0.2.1/lib/channel/channel.dart:54:21)
E/flutter ( 2680): #6      _MapStream._handleData (dart:async/stream_pipe.dart:227:21)
E/flutter ( 2680): #7      _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
E/flutter ( 2680): #8      _RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10)
E/flutter ( 2680): #9      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330:11)
E/flutter ( 2680): #10     _DelayedData.perform (dart:async/stream_impl.dart:578:14)
E/flutter ( 2680): #11     _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694:11)
E/flutter ( 2680): #12     _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654:7)
E/flutter ( 2680): #13     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter ( 2680): #14     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
I/flutter ( 5830): monitoring: {"data":"enter","isSuccessful":true,"region":{"identifier":"test","ids":["d9407f30-f5f8-466e-aff9-25556b57fe6d"]}}```

My Device:
Samsung Galaxy S7
Android 7.0

Background monitoring stops when terminating app on Android 7

I'm running the example app on a Huawei Honor 6X with Android 7.0, and monitoring works fine as long as the app is running, i.e. it is either visible or just "minimized" by pressing the home button. If I force close the app or terminate it from the recent apps list (not sure if that does the same thing as a force close?), background monitoring events fail to produce notifications.

From reading the Background monitoring section in the README, I'm under the impression that background monitoring should continue even if the app is terminated? Sadly, this is not the case on my device. And since Android can kill apps unexpectedly, this behavior kind of means that this plugin doesn't really support background monitoring in any practical sense. Normal smartphone users wouldn't expect that they need to open the app periodically to make sure it's not terminated, they expect to install the app, open it once and then never have to do anything again but still receive beacon events in the background, just like SMS or calls.

Is this project actually abandoned?

I can see that the author did not accept pull request to fix the Gradle crashes, and the Github repo hasn't been updated for about a half year.
I have just saw/wrote some alternatives here:

  1. https://github.com/alann-maulana/flutter_beacon Just googled this, going to pull it and check if this will work.
  2. https://github.com/michaellee8/flutter_blue_beacon Spinned up my own library wrapping flutter_blue. Scanning iBeacon in iOS is not going to work therefore, since Apple require native scanning for iBeacon. No support to background scanning right now.

Stop ranging / monitoring?

Does cancelling a subscription automatically stop the ranging and monitoring on the device (i.e. call stopMonitoringForRegion / stopRangingForRegion)?

Or is there another way to do this?

Thanks!

Not detecting changes when app is killed (iOS)

After killing the app we're are not getting any notifications when we enter and exit regions on iOS.

I suspect it's because the notifyEntryStateOnDisplay is not getting set to true by default.

To recreate, monitor a region and write a value to database each time enter and exit region, kill the app, enter/exit region => no change detected in database.

Beacons stopMonitoring doesn't stop monitoring the specified region

Hi,

i am trying to stop monitoring a beacon region but its not working. The message i receive is the following:
beacons: invoke beacons->stopMonitoring {"identifier":"b65de587b6494010af5bb6a733fc8ddd","ids":["b65de587-b649-4010-af5b-b6a733fc8ddd"],"bluetoothAddress":null}I/flutter (13139): beacons: finished without data

[ERROR]java.lang.IllegalArgumentException: Service not registered: org.altbeacon.beacon.BeaconManager$BeaconServiceConnection@ce5387c

E/AndroidRuntime(15227): java.lang.RuntimeException: Unable to destroy activity {com.example.finalparola/com.google.android.gms.auth.api.signin.internal.SignInHubActivity}: java.lang.IllegalArgumentException: Service not registered: org.altbeacon.beacon.BeaconManager$BeaconServiceConnection@ce5387c E/AndroidRuntime(15227): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5139) E/AndroidRuntime(15227): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:5162) E/AndroidRuntime(15227): at android.app.ActivityThread.access$1700(ActivityThread.java:229) E/AndroidRuntime(15227): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1880) E/AndroidRuntime(15227): at android.os.Handler.dispatchMessage(Handler.java:102) E/AndroidRuntime(15227): at android.os.Looper.loop(Looper.java:148) E/AndroidRuntime(15227): at android.app.ActivityThread.main(ActivityThread.java:7325) E/AndroidRuntime(15227): at java.lang.reflect.Method.invoke(Native Method) E/AndroidRuntime(15227): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1321) E/AndroidRuntime(15227): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1211) E/AndroidRuntime(15227): Caused by: java.lang.IllegalArgumentException: Service not registered: org.altbeacon.beacon.BeaconManager$BeaconServiceConnection@ce5387c E/AndroidRuntime(15227): at android.app.LoadedApk.forgetServiceDispatcher(LoadedApk.java:1160) E/AndroidRuntime(15227): at android.app.ContextImpl.unbindService(ContextImpl.java:1475) E/AndroidRuntime(15227): at android.content.ContextWrapper.unbindService(ContextWrapper.java:644) E/AndroidRuntime(15227): at io.intheloup.beacons.logic.BeaconsClient.unbindService(BeaconsClient.kt:246) E/AndroidRuntime(15227): at org.altbeacon.beacon.BeaconManager.unbind(BeaconManager.java:453) E/AndroidRuntime(15227): at io.intheloup.beacons.logic.BeaconsClient.unbind(BeaconsClient.kt:61) E/AndroidRuntime(15227): at io.intheloup.beacons.BeaconsPlugin$1.onActivityDestroyed(BeaconsPlugin.kt:35) E/AndroidRuntime(15227): at android.app.Application.dispatchActivityDestroyed(Application.java:275) E/AndroidRuntime(15227): at android.app.Activity.onDestroy(Activity.java:1883) E/AndroidRuntime(15227): at android.support.v4.app.FragmentActivity.onDestroy(FragmentActivity.java:382) E/AndroidRuntime(15227): at android.app.Activity.performDestroy(Activity.java:7130) E/AndroidRuntime(15227): at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1171) E/AndroidRuntime(15227): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:5117) E/AndroidRuntime(15227): ... 9 more

I have Google sign in package, and when I try to log in in my physical device, this gives me an error. while on emulator, it doesnt, because emulators don't have bluetooth.

References to this Issue >> AltBeacon/android-beacon-library#139

Issues with using this plugin in newest version of flutter

I was having the same initial errors as defined in issue #1. However, after following the instructions, I now no longer get an error, instead don't get a build at all. The Xcode build time doubled, and now the application hangs on the Install and Launch option.

Flutter version: 1.0
CocoaPods version: 1.5.3

I've attached my pod file if that helps.
Podfile.zip

Never ending console output on android

When using the plugin there is a continuous stream of the following output:

...
D/ScanRecord( 5830): parseFromBytes
D/ScanRecord( 5830): first manudata for manu ID
D/ScanRecord( 5830): parseFromBytes
D/ScanRecord( 5830): first manudata for manu ID
D/ScanRecord( 5830): parseFromBytes
D/ScanRecord( 5830): first manudata for manu ID
D/ScanRecord( 5830): parseFromBytes
D/ScanRecord( 5830): first manudata for manu ID
D/ScanRecord( 5830): parseFromBytes
D/ScanRecord( 5830): first manudata for manu ID
...

This doesn't affect anything but makes debugging anything else extremely difficult.

There is a new output at least every second.

I would love if there is a way to suppress these messages.

Can't run or build for Android

(master) ➜ flutter build appbundle 035fef9
Waiting for another flutter command to release the startup lock...

FAILURE: Build failed with an exception.

  • What went wrong:
    The Android Gradle plugin supports only Kotlin Gradle plugin version 1.3.10 and higher.
    The following dependencies do not satisfy the required version:
    project ':beacons' -> org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.41

Slow Startup When Inside Region; Conflicting Events

Thanks for the excellent library! We're trying to use it as part of an app for CS 125 @ Illinois to track when our course staff (and eventually students) come and go into a room that we use for office hours. Source code is here: https://github.com/gchallen/cs125_app. I'm very new to flutter and to Dart so am just trying to get something simple working that logs when regions are entered and exited from.

I'm having two problems at present. First, the library seems slow to report when the app is restarted inside an existing region. This is in contrast to the fairly quick reports that are generated when regions are exited or entered, or when I turn the beacon on and off—those appear within a few seconds. When I do a restart of the app with an existing beacon nearby, several minutes go by before the first reports are received. However, the library does seem to know it's inside an existing region based on this message from the logs:

06-21 09:18:38.711 20541-20541/edu.illinois.cs.cs125.cs125app I/ScanJob: We are inside a beacon region.  We will not scan between cycles.

So is there a way to query on startup to determine the current region? I didn't see that in the API description, although not everything seems to be documented yet.

Second, the beacon does begin to be reported I'm getting repeated pairs of exited region + entered region messages back to back. That doesn't seem to happen in other scenarios: for example, when I turn the beacon on and off I get one message back, not a pair. Obviously we could do some debouncing in our app but I thought perhaps this was related to the issue I described above.

Upgrade to Kotlin 1.3

Currently the beacon library runs with Kotlin 1.2.x which results in the error "coroutines cannot be used in release mode". This means I cannot run the library at all on Android.

Please upgrade to Kotlin 1.3.x to fix this error.

FYI I have actually upgraded the library to Kotlin 1.3 myself but I'm hesitant to perform a pull request as the changes are quite intensive.

Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'. > Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'. > Could not find org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.70. Required by: project :app

Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'.

Could not resolve all task dependencies for configuration ':app:debugCompileClasspath'.
Could not find org.jetbrains.kotlin:kotlin-stdlib-jre7:1.3.70.
Required by:
project

  1. what is this issue? How can I correct it?
  2. why will I use this kotlin, if I am doing flutter dart language project?

Build failed

FAILURE: Build failed with an exception.

  • What went wrong:
    The Android Gradle plugin supports only Kotlin Gradle plugin version 1.2.51 and higher. Project 'beacons' is using version 1.2.41.

  • Try:

Background monitoring on Android

Users implementing background monitoring are required to subclass FlutterApplication on the Android side:

class App : FlutterApplication() {

    override fun onCreate() {
        super.onCreate()

        BeaconsPlugin.init(this, object : BeaconsPlugin.BackgroundMonitoringCallback {
            override fun onBackgroundMonitoringEvent(event: BackgroundMonitoringEvent): Boolean {
                // callback when a monitoring event is detected in background
                // start flutter activity, or do something else custom in java/kotlin
                val intent = Intent(this@App, MainActivity::class.java)
                startActivity(intent)
                return true
            }
        })
    }
}

Once alarm_manager is fixed (flutter/flutter#17566), this library will expose a similar API: a callback purely written in Dart on the Flutter side.

BeaconRegionIBeacon at ranging: Unable to parse Identifier.

Hi

I am trying to pass a BeaconRegionIBeacon through the ranging() method but when i pass the major and minor as Int, ranging breaks with the message (Unable to parse Identifier.) and shows me that the minor and major, previously set as int, have been converted to double.

I am actually trying to fix this issue, but if anyone can help me I would appreciate it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.