Flutter plugin (android) for sharing bytes and files Offline, (Based on the android Nearby Connections API)

Overview

nearby_connections

An android flutter plugin for the Nearby Connections API Currently supports Bytes and Files.

Transfer Data between multiple connected devices using fully offline peer to peer networking

pub package Stars Forks

Table of Content

Setup

Note regarding Location(GPS)

While using this, Location/GPS service must be turned on or devices may disconnect more often, some devices may disconnect immediately.

Set Permissions

Add these to AndroidManifest.xml

<!-- Required for Nearby Connections -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<!-- Optional: only required for FILE payloads-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<!-- For Android 12+ support-->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Note: Android 12+ has introduced some new bluetooh permissions - BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, which need to be handled as well. You may also need to set compileSdkVersion 32 in your build.gradle file.

Since ACCESS_FINE_LOCATION and READ_EXTERNAL_STORAGE is considered to be dangerous system permissions, in addition to adding them to your manifest, you must request these permissions at runtime.

You can use the permission_handler package to handle all these permissions.

Otherwise, as a convenience this library provides methods to check and request location and external read/write permissions

// returns true/false asynchronously.
bool a = await Nearby().checkLocationPermissions();
// asks for permission only if its not given
// returns true/false if the location permission is granted on/off resp.
bool b = await Nearby().askLocationPermission();

// OPTIONAL: if you need to transfer files and rename it on device
bool c = await  Nearby().checkExternalStoragePermission();
// asks for READ + WRTIE EXTERNAL STORAGE permission only if its not given
Nearby().askExternalStoragePermission();

Nearby().askLocationAndExternalStoragePermission(); // for all permissions in one go..

// For bluetooth permissions on Android 12+.
bool d = await Nearby().checkBluetoothPermission();
// asks for BLUETOOTH_ADVERTISE, BLUETOOTH_CONNECT, BLUETOOTH_SCAN permissions.
Nearby().askBluetoothPermission();

Work Flow

The work flow is similar to the Android Nearby Connections library

NOTE

Location/GPS service must be turned on or devices may disconnect more often, some devices may disconnect immediately.

For convenience this library provides methods to check and enable location

bool b = await Nearby().checkLocationEnabled();

// opens dialogue to enable location service
// returns true/false if the location service is turned on/off resp.
bool b = await Nearby().enableLocationServices();

Advertise for connection

try {
    bool a = await Nearby().startAdvertising(
        userName,
        strategy,
        onConnectionInitiated: (String id,ConnectionInfo info) {
        // Called whenever a discoverer requests connection 
        },
        onConnectionResult: (String id,Status status) {
        // Called when connection is accepted/rejected
        },
        onDisconnected: (String id) {
        // Callled whenever a discoverer disconnects from advertiser
        },
        serviceId: "com.yourdomain.appname", // uniquely identifies your app
    );
} catch (exception) {
    // platform exceptions like unable to start bluetooth or insufficient permissions 
}

Discover Advertisers

try {
    bool a = await Nearby().startDiscovery(
        userName,
        strategy,
        onEndpointFound: (String id,String userName, String serviceId) {
            // called when an advertiser is found
        },
        onEndpointLost: (String id) {
            //called when an advertiser is lost (only if we weren't connected to it )
        },
        serviceId: "com.yourdomain.appname", // uniquely identifies your app
    );
} catch (e) {
    // platform exceptions like unable to start bluetooth or insufficient permissions
}

Stopping Advertising and Discovery

Nearby().stopAdvertising();
Nearby().stopDiscovery();
// endpoints already discovered will still be available to connect
// even after stopping discovery
// You should stop discovery once you have found the intended advertiser
// this will reduce chances for disconnection

Request Connection

// to be called by discover whenever an endpoint is found
// callbacks are similar to those in startAdvertising method
try{ 
    Nearby().requestConnection(
        userName,
        id,
        onConnectionInitiated: (id, info) {
        },
        onConnectionResult: (id, status) {
        },
        onDisconnected: (id) {
        },
    );
}catch(exception){
    // called if request was invalid
}

Accept Connection

Nearby().acceptConnection(
    id,
    onPayLoadRecieved: (endpointId, payload) {
        // called whenever a payload is recieved.
    },
    onPayloadTransferUpdate: (endpointId, payloadTransferUpdate) {
        // gives status of a payload
        // e.g success/failure/in_progress
        // bytes transferred and total bytes etc
    }
);

Sending Data

Sending Bytes Payload

Nearby().sendBytesPayload(endpointId, bytes_array);

// payloads are recieved by callback given to acceptConnection method.

Sending File Payload

You need to send the File Payload and File Name seperately.

File is stored in DOWNLOAD_DIRECTORY/.nearby/ and given a generic name. You need to copy the file to another directory of your choice.

//creates file with generic name (without extension) in Downloads Directory
//its your responsibility to rename the file properly
Nearby().sendFilePayload(endpointId, filePath);

//Send filename as well so that receiver can move and rename the file
Nearby().sendBytesPayload(endpointId,fileNameEncodedWithPayloadId);
//e.g send a string like "payloadId:FileExtensionOrFullName" as bytes

//payloads are recieved by callback given to acceptConnection method.

Every payload has an ID which is same for sender and receiver.

You can get the uri of the file from Payload in onPayloadReceived function. We have a convinience method to copy the file to a location you want-

// Convinience method to copy file using it's `uri`.
final newPath = '${await getExternalStorageDirectory}/$fileName';
await Nearby().copyFileAndDeleteOriginal(uri, newPath);

Checkout the Example in Repository for more details.

Comments
  • Failed to build after upgrading to Flutter stable v 2.2.2: cannot find symbol VERSION_CODES.Q

    Failed to build after upgrading to Flutter stable v 2.2.2: cannot find symbol VERSION_CODES.Q

    Before I upgraded to the latest version of Flutter, there wasn't any errors while building the application. After running flutter upgrade and then run flutter run --verbose I got the following error.

    [        ] > Task :nearby_connections:generateDebugBuildConfig
    [  +97 ms] > Task :permission_handler:generateDebugBuildConfig
    [  +99 ms] > Task :permission_handler:javaPreCompileDebug
    [ +900 ms] > Task :permission_handler:compileDebugJavaWithJavac
    [        ] > Task :nearby_connections:javaPreCompileDebug
    [ +599 ms] > Task :nearby_connections:compileDebugJavaWithJavac FAILED
    [        ] > Task :permission_handler:bundleLibCompileDebug
    [        ]
    /home/apt/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/nearby_connections-3.1.0/android/src/main/java/com/pkmnapps/nearby_con
    nections/NearbyConnectionsPlugin.java:448: error: cannot find symbol
    [        ]                 if (VERSION.SDK_INT < VERSION_CODES.Q) {
    [        ]                                                    ^
    [        ]   symbol:   variable Q
    [        ]   location: class VERSION_CODES
    [        ] Note:
    /home/apt/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/nearby_connections-3.1.0/android/src/main/java/com/pkmnapps/nearby_con
    nections/NearbyConnectionsPlugin.java uses or overrides a deprecated API.
    [        ] Note: Recompile with -Xlint:deprecation for details.
    [        ] 1 error
    [ +197 ms] FAILURE: Build failed with an exception.
    [        ] * What went wrong:
    [        ] Execution failed for task ':nearby_connections:compileDebugJavaWithJavac'.
    [        ] > Compilation failed; see the compiler error output for details.
    [        ] * Try:
    [        ] Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to
    get full insights.
    [   +4 ms] * Get more help at https://help.gradle.org
    [        ] BUILD FAILED in 18m 14s
    [        ] 215 actionable tasks: 214 executed, 1 up-to-date
    [+1552 ms] Running Gradle task 'assembleDebug'... (completed in 1096.6s)
    [  +25 ms] Exception: Gradle task assembleDebug failed with exit code 1
    [   +3 ms] "flutter run" took 1,101,056ms.
    [  +10 ms] 
               #0      throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
               #1      RunCommand.runCommand (package:flutter_tools/src/commands/run.dart:663:9)
               <asynchronous suspension>
               #2      FlutterCommand.run.<anonymous closure> (package:flutter_tools/src/runner/flutter_command.dart:1043:27)
               <asynchronous suspension>
               #3      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #4      CommandRunner.runCommand (package:args/command_runner.dart:196:13)
               <asynchronous suspension>
               #5      FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:284:9)
               <asynchronous suspension>
               #6      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #7      FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:232:5)
               <asynchronous suspension>
               #8      run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
               <asynchronous suspension>
               #9      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #10     main (package:flutter_tools/executable.dart:91:3)
               <asynchronous suspension>
               
               
    [   +6 ms] Running shutdown hooks
    [   +1 ms] Shutdown hooks complete
    [   +2 ms] exiting with code 1
    

    Looks like there is a problem with the VERSION_CODES.Q in nearby_connections package.

    The following is my environment details from the command flutter doctor --verbose

    [✓] Flutter (Channel stable, 2.2.2, on Linux, locale en_US.UTF-8)
        • Flutter version 2.2.2 at /home/apt/snap/flutter/common/flutter
        • Framework revision d79295af24 (3 days ago), 2021-06-11 08:56:01 -0700
        • Engine revision 91c9fc8fe0
        • Dart version 2.13.3
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
        • Android SDK at /home/apt/Android/Sdk
        • Platform android-30, build-tools 30.0.3
        • Java binary at: /usr/local/android-studio/jre/bin/java
        • Java version OpenJDK Runtime Environment (build
          1.8.0_242-release-1644-b3-6222593)
        • All Android licenses accepted.
    
    [✓] Chrome - develop for the web
        • Chrome at google-chrome
    
    [✓] Android Studio (version 4.1)
        • Android Studio at /usr/local/android-studio
        • Flutter plugin version 53.1.1
        • Dart plugin version 201.9317
        • Java version OpenJDK Runtime Environment (build
          1.8.0_242-release-1644-b3-6222593)
    
    [✓] Connected device (2 available)
        • MYA L22 (mobile) • R9KBB17807153597 • android-arm64  • Android 6.0 (API
          23)
        • Chrome (web)     • chrome           • web-javascript • Google Chrome
          91.0.4472.101
    
    • No issues found!
    
    

    Thank you in advance for your response, and also thanks for maintaining this project 👍

    opened by aptarmy 12
  • files not receiving on android 11

    files not receiving on android 11

    Error Logs D/nearby_connections(17721): ad.onConnectionResult D/nearby_connections(17721): onPayloadReceived D/nearby_connections(17721): onPayloadTransferUpdate I/flutter (17721): Tt3c: -4780165049267211412:IMG_20210409_181224.jpg I/flutter (17721): NoSuchMethodError: The method 'exists' was called on null. I/flutter (17721): Receiver: null I/flutter (17721): Tried calling: exists() I/flutter (17721): InProgress D/nearby_connections(17721): onPayloadTransferUpdate I/flutter (17721): Success W/NearbyConnections(17721): Failed to create Payload from ParcelablePayload: Java file not found at /storage/emulated/0/Download/.nearby/-4780165049267211412 W/NearbyConnections(17721): java.io.FileNotFoundException: open failed: EACCES (Permission denied) W/NearbyConnections(17721): at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:344) W/NearbyConnections(17721): at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:231) W/NearbyConnections(17721): at com.google.android.gms.nearby.connection.Payload$File.zza(Unknown Source:12) W/NearbyConnections(17721): at com.google.android.gms.internal.nearby.zzfl.zza(Unknown Source:81) W/NearbyConnections(17721): at com.google.android.gms.internal.nearby.zzav.zza(Unknown Source:5) W/NearbyConnections(17721): at com.google.android.gms.internal.nearby.zzdx.dispatchTransaction(Unknown Source:28) W/NearbyConnections(17721): at com.google.android.gms.internal.nearby.zzb.onTransact(Unknown Source:22) W/NearbyConnections(17721): at android.os.Binder.execTransactInternal(Binder.java:1159) W/NearbyConnections(17721): at android.os.Binder.execTransact(Binder.java:1123) D/nearby_connections(17721): onPayloadReceived D/AndroidRuntime(17721): Shutting down VM E/AndroidRuntime(17721): FATAL EXCEPTION: main
    opened by devalanrs 9
  • onEndpointFound never called

    onEndpointFound never called

    Hi! I want to use your plugin in my app, but i have a problem: after Nearby().startDiscovery(), in the console i find :

    D/nearby_connections( 4515): startDiscovery D/nearby_connections( 4515): onEndpointFound

    but the onEndpointFound method from my app is never called. In fact, the _channel.setMethodCallHandler method from nearby_connections.dart is never called.

    The example app from your plugin is working fine, it seems that is some sort of conflict between this plugin and other plugin from my app, but i don't know which.

    Please, do you have any idea on how to solve this? Thank you very much!

    Later edit:

    I found the plugin that conflicts with this one, is firebase_messaging, particularly this method:

      public static void startBackgroundIsolate(Context context, long callbackHandle) {
        FlutterMain.ensureInitializationComplete(context, null);
        String appBundlePath = FlutterMain.findAppBundlePath();
        FlutterCallbackInformation flutterCallback =
            FlutterCallbackInformation.lookupCallbackInformation(callbackHandle);
        if (flutterCallback == null) {
          Log.e(TAG, "Fatal: failed to find callback");
          return;
        }
    
        // Note that we're passing `true` as the second argument to our
        // FlutterNativeView constructor. This specifies the FlutterNativeView
        // as a background view and does not create a drawing surface.
        backgroundFlutterView = new FlutterNativeView(context, true);
        if (appBundlePath != null && !isIsolateRunning.get()) {
          if (pluginRegistrantCallback == null) {
            throw new RuntimeException("PluginRegistrantCallback is not set.");
          }
          FlutterRunArguments args = new FlutterRunArguments();
          args.bundlePath = appBundlePath;
          args.entrypoint = flutterCallback.callbackName;
          args.libraryPath = flutterCallback.callbackLibraryPath;
          backgroundFlutterView.runFromBundle(args);
          pluginRegistrantCallback.registerWith(backgroundFlutterView.getPluginRegistry());
        }
      }
    

    Unfortunately, i don't know how to solve this....

    opened by sd-timaru 9
  • onEndpointFound and onConnectionInitiated function never get called

    onEndpointFound and onConnectionInitiated function never get called

    Previously, nearby_connection v2.0.2 is working fine, but after adding firebase_messaging v8.0.0-dev.15 to the app, onEndpointFound and onConnectionInitiated never get called.

    I have a git commit of a working app (onEndpointFound and onConnectionInitiated get called correctly, before adding firebase_messaging) and the latest git commit that integrated firebase_messaging where nearby_connection started to break.

    I ran this command git diff <hash before nearby_connection breaks> <hash of firebase_messaging integration>, the result is pretty clear that all code related to nearby_connections is intanct. There is no new code related to nearby_connections.

    When I do git checkout to the commit before integrating firebase_messaging, nearby_connections works great. But as soon as git checkout to the firebase_messaging integration commit, it breaks.

    The environment is the same as before and after nearby_connections breaks.

    diff --git a/android/app/build.gradle b/android/app/build.gradle
    index 33df214..ab3dd80 100644
    --- a/android/app/build.gradle
    +++ b/android/app/build.gradle
    @@ -23,6 +23,7 @@ if (flutterVersionName == null) {
     
     apply plugin: 'com.android.application'
     apply plugin: 'kotlin-android'
    +apply plugin: 'com.google.gms.google-services'
     apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
     
     android {
    @@ -59,5 +60,8 @@ flutter {
     }
     
     dependencies {
    +    implementation platform('com.google.firebase:firebase-bom:25.3.1')
    +    implementation 'com.google.firebase:firebase-analytics-ktx'
         implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
     }
    diff --git a/android/app/google-services.json b/android/app/google-services.json
    new file mode 100644
    index 0000000..1dd6783
    --- /dev/null
    +++ b/android/app/google-services.json
    @@ -0,0 +1,40 @@
    +{
    +  "project_info": { ... }
    +}
    \ No newline at end of file
    diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
    index 2878b8a..73e8407 100644
    --- a/android/app/src/main/AndroidManifest.xml
    +++ b/android/app/src/main/AndroidManifest.xml
    @@ -66,6 +66,8 @@
             <meta-data android:name="flutterEmbedding" android:value="2" />
             <!-- Google map -->
             <meta-data android:name="com.google.android.geo.API_KEY" android:value="XXXX"/>
    +        <!-- A custom Android Notification Channel to deliver FCM notifications on a non-default channel -->
    +        <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id" android:value="high_importance_channel" />
         </application>
     
         <!-- Required for Nearby Connections -->
    @@ -90,4 +92,4 @@
     
         <!-- Internet -->
         <uses-permission android:name="android.permission.INTERNET" />
    -</manifest>
    \ No newline at end of file
    +</manifest>
    diff --git a/android/build.gradle b/android/build.gradle
    index 3100ad2..bb6f91b 100644
    --- a/android/build.gradle
    +++ b/android/build.gradle
    @@ -8,6 +8,7 @@ buildscript {
         dependencies {
             classpath 'com.android.tools.build:gradle:3.5.0'
             classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    +        classpath 'com.google.gms:google-services:4.3.8'
         }
     }
     
    diff --git a/lib/main.dart b/lib/main.dart
    index 8fbf391..b2db7e1 100644
    --- a/lib/main.dart
    +++ b/lib/main.dart
    @@ -2,13 +2,17 @@ import 'dart:async';
     import 'dart:io';
     import 'dart:convert';
     import 'dart:math';
    +import 'package:http/http.dart';
     import 'package:flutter/material.dart';
    +import 'package:flutter/foundation.dart';
     import 'package:provider/provider.dart';
     import 'package:nearby_connections/nearby_connections.dart';
     import 'package:flutter_blue/flutter_blue.dart';
     import 'package:flutter_local_notifications/flutter_local_notifications.dart';
     import 'package:mime/mime.dart';
     import 'package:geolocator/geolocator.dart';
    +import 'package:firebase_core/firebase_core.dart';
    +import 'package:firebase_messaging/firebase_messaging.dart';
     
     import 'package:rpd_prototype/helpers/database.dart';
     import 'package:rpd_prototype/helpers/BleCharRef.dart';
    @@ -27,12 +31,50 @@ import 'package:rpd_prototype/pages/qzqsmMessages.dart';
     import 'package:rpd_prototype/pages/user.dart';
     import 'package:rpd_prototype/pages/warning.dart';
     
    +FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    +
     void main() async {
       WidgetsFlutterBinding.ensureInitialized();
       await SqLiteDatabase.initializeDb();
    +  await firebaseMessagingSetup();
       runApp(MyApp());
     }
     
    +Future<void> firebaseMessagingSetup() async {
    +  await Firebase.initializeApp();
    +  FirebaseMessaging.onBackgroundMessage(firebaseBackgroundMessageHandler);
    +  /// Create a [AndroidNotificationChannel] for heads up notifications
    +  const AndroidNotificationChannel channel = AndroidNotificationChannel(
    +    'high_importance_channel', // id
    +    'High Importance Notifications', // title
    +    'This channel is used for important notifications.', // description
    +    importance: Importance.high,
    +    enableVibration: true,
    +    playSound: true,
    +  );
    +  if (defaultTargetPlatform == TargetPlatform.android) {
    +    /// Create an Android Notification Channel.
    +    ///
    +    /// We use this channel in the `AndroidManifest.xml` file to override the
    +    /// default FCM channel to enable heads up notifications.
    +    await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel);
    +  }
    +  /// Update the iOS foreground notification presentation options to allow
    +  /// heads up notifications.
    +  await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
    +    alert: true,
    +    badge: true,
    +    sound: true,
    +  );
    +}
    +
    +Future<void> firebaseBackgroundMessageHandler(RemoteMessage message) async {
    +  print(">>> firebaseBackgroundMessageHandler: ${message.data}");
    +  if(message.notification != null) {
    +    print(">>> message also contained notification: ${message.notification}");
    +  }
    +}
    +
     class MyApp extends StatelessWidget {
       // This widget is the root of your application.
       @override
    @@ -89,12 +131,15 @@ class MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
       Timer flutterBlueReadDataTimeout;
       Timer flutterBlueScanTimer;
       StreamSubscription<BluetoothState> streamBluetoothSubscription;
    -  FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
       Map<int, File> tempFiles = {}; // { payloadId: file }
       Map<int, Map<String, dynamic>> tempFileData = {}; // { payloadId: { String fileName, String senderDisplayName, DateTime timestamp } }
     
       StreamSubscription<Position> userPositionStream;
     
    +  // Firebase messaging
    +  StreamSubscription<RemoteMessage> firebaseMessagingForegroundSubscription;
    +  StreamSubscription<RemoteMessage> firebaseMessagingAppOpenedSubscription;
    +
       void initState() {
         super.initState();
         WidgetsBinding.instance.addObserver(this);
    @@ -108,6 +153,9 @@ class MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
         var initSetttings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsIOs);
         flutterLocalNotificationsPlugin.initialize(initSetttings, onSelectNotification: onSelectNotification);
     
    +    // Firebase Messaging
    +    firebaseMessagingListenForeground();
    + 
         MessageQueue.watchQueue(connectedDeviceModel);
         nearbyCheckPermission();
         timerToggleNearbyAdvertiseDiscovery();
    @@ -116,6 +164,44 @@ class MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
         subscribeUserPosition();
       }
     
    +  void firebaseMessagingListenForeground() async { 
    +    FirebaseMessaging.instance.getToken().then((value) {
    +      print(">>> got firebase token: $value");
    +      post("http://192.168.1.38:8000/api/add-firebase-messaging-token", headers: { 'content-type': 'application/json; charset=UTF-8' }, body: jsonEncode({ "token": value })).then((res) {
    +        print(">>> sent firebase token to 192.168.1.38:8000");
    +      }).catchError((error) {
    +        print(">>> Error while sending token to 192.168.1.38:8000");
    +        print(error);
    +      });
    +    });
    +    // Firebase messaging
    +    firebaseMessagingForegroundSubscription = FirebaseMessaging.onMessage.listen((RemoteMessage message) {
    +      print(">>> received firebase foreground message: ${message.data.toString()}");
    +      handleFirebaseMessaging(message);
    +    });
    +    firebaseMessagingAppOpenedSubscription = FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
    +      print(">>> onMessageOpenedApp: ${message.data.toString()}");
    +      handleFirebaseMessaging(message);
    +    });
    +  }
    +
    +  Future<void> handleFirebaseMessaging(RemoteMessage message) async {
    +    String qzqsm = message.data["qzqsm"];
    +    List<ConnectedDevice> devices = connectedDeviceModel.devices.where((device) => device.type == ConnectedDeviceType.nearbyDevice).toList();
    +    // if message is QZQSM
    +    if(QzqsmMessageListModel.isQzqsmString(qzqsm)) {
    +      QzqsmMessage qzqsmMessage = await handleQzqsmInput(qzqsm);
    +      // if message is already received, do nothing
    +      if(qzqsmMessage == null) { return; }
    +      // send EWS to others
    +      for(int i=0; i<devices.length; i++) {
    +        print(">>> RECEIVED PUSHED QZQSM TO MOBILE >>> mobile: ${devices[i].id}, qzqsm: ${qzqsmMessage.qzqsmString}");
    +        MessageQueue.add(MessageType.TEXT, devices[i].id, "QZQSM>${qzqsmMessage.qzqsmString}");
    +        await SqLiteDatabase.associateDeviceWithEWS(deviceId: devices[i].name, ewsBinPayload: qzqsmMessage.binPayload);
    +      }
    +    }
    +  }
    + 
       void didChangeAppLifecycleState(AppLifecycleState state) {
         setState(() { appLifecycleState = state; });
         print(">>> app state changes: ${state.toString()}");
    @@ -813,5 +899,8 @@ class MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
         super.dispose();
         SqLiteDatabase.instance.close();
         ChatMessageDBStream.dispose();
    +    // Firebase Messaging dispose
    +    firebaseMessagingForegroundSubscription?.cancel();
    +    firebaseMessagingAppOpenedSubscription?.cancel();
       }
     }
    diff --git a/pubspec.lock b/pubspec.lock
    index 1eb7696..ecfdb5b 100644
    --- a/pubspec.lock
    +++ b/pubspec.lock
    @@ -8,13 +8,6 @@ packages:
           url: "https://pub.dartlang.org"
         source: hosted
         version: "2.5.0"
       boolean_selector:
         dependency: transitive
         description:
    @@ -91,7 +84,7 @@ packages:
           name: device_info
           url: "https://pub.dartlang.org"
         source: hosted
    -    version: "2.0.0"
    +    version: "2.0.2"
       device_info_platform_interface:
         dependency: transitive
         description:
    @@ -120,6 +113,48 @@ packages:
           url: "https://pub.dartlang.org"
         source: hosted
         version: "5.2.1"
    +  firebase_core:
    +    dependency: "direct main"
    +    description:
    +      name: firebase_core
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "0.7.0"
    +  firebase_core_platform_interface:
    +    dependency: transitive
    +    description:
    +      name: firebase_core_platform_interface
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "3.0.1"
    +  firebase_core_web:
    +    dependency: transitive
    +    description:
    +      name: firebase_core_web
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "0.2.1+3"
    +  firebase_messaging:
    +    dependency: "direct main"
    +    description:
    +      name: firebase_messaging
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "8.0.0-dev.15"
    +  firebase_messaging_platform_interface:
    +    dependency: transitive
    +    description:
    +      name: firebase_messaging_platform_interface
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "1.0.0-dev.10"
    +  firebase_messaging_web:
    +    dependency: transitive
    +    description:
    +      name: firebase_messaging_web
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "0.1.0-dev.6"
       fixnum:
         dependency: transitive
         description:
    @@ -436,6 +471,13 @@ packages:
           url: "https://pub.dartlang.org"
         source: hosted
         version: "4.3.2+2"
    +  quiver:
    +    dependency: transitive
    +    description:
    +      name: quiver
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "2.1.5"
       recase:
         dependency: transitive
         description:
    @@ -450,6 +492,13 @@ packages:
           url: "https://pub.dartlang.org"
         source: hosted
         version: "0.24.1"
    +  service_worker:
    +    dependency: transitive
    +    description:
    +      name: service_worker
    +      url: "https://pub.dartlang.org"
    +    source: hosted
    +    version: "0.2.4"
       sky_engine:
         dependency: transitive
         description: flutter
    @@ -610,5 +659,5 @@ packages:
         source: hosted
         version: "0.1.2"
     sdks:
    -  dart: ">=2.12.0-259.9.beta <3.0.0"
    +  dart: ">=2.12.0 <3.0.0"
       flutter: ">=1.22.2"
    diff --git a/pubspec.yaml b/pubspec.yaml
    index 6ddcf2c..b6f474c 100644
    --- a/pubspec.yaml
    +++ b/pubspec.yaml
    @@ -29,7 +29,7 @@ dependencies:
       nearby_connections: ^2.0.2
       flutter_blue: ^0.7.2
       flutter_local_notifications: ^3.0.1+5
       image_picker: ^0.6.7+22
       mime: ^0.9.7
       video_player: ^1.0.1
    @@ -51,6 +51,10 @@ dependencies:
       # SQLite database
       sqflite:
     
    +  # Firebase Push Notification
    +  firebase_core: "^0.7.0"
    +  firebase_messaging: "^8.0.0-dev.15"
    +
     dev_dependencies:
       flutter_test:
         sdk: flutter
    

    However, it looks like nearby_connections knows when it find new endpoint, as I see this in the terminal.

    D/nearby_connections(26285): startDiscovery
    D/nearby_connections(26285): onEndpointFound
    

    But for some reason, onEndpointFound and onConnectionInitiated never get called.

    This my flutter doctor -v

    [✓] Flutter (Channel dev, 1.27.0-8.0.pre, on Linux, locale en_US.UTF-8)
        • Flutter version 1.27.0-8.0.pre at /home/apt/snap/flutter/common/flutter
        • Framework revision b7d4806243 (4 months ago), 2021-02-19 09:22:45 -0800
        • Engine revision 6993cb229b
        • Dart version 2.13.0 (build 2.13.0-30.0.dev)
    
    [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
        • Android SDK at /home/apt/Android/Sdk
        • Platform android-30, build-tools 30.0.3
        • Java binary at: /usr/local/android-studio/jre/bin/java
        • Java version OpenJDK Runtime Environment (build 11.0.8+0-b944-P17168821)
        • All Android licenses accepted.
    
    [✓] Chrome - develop for the web
        • Chrome at google-chrome
    
    [✓] Android Studio
        • Android Studio at /usr/local/android-studio
        • Flutter plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/9212-flutter
        • Dart plugin can be installed from:
          🔨 https://plugins.jetbrains.com/plugin/6351-dart
        • android-studio-dir = /usr/local/android-studio
        • Java version OpenJDK Runtime Environment (build 11.0.8+0-b944-P17168821)
    
    [✓] Connected device (2 available)
        • SM A015F (mobile) • R9JN20BEXCJ • android-arm    • Android 10 (API 29)
        • Chrome (web)      • chrome      • web-javascript • Google Chrome 91.0.4472.101
    
    • No issues found!
    

    I have no idea why nearby_connections break as I didn't touch any code related to nearby_connections, so it is possibly a bug in nearby_connections. Thank you in advance for your response.

    opened by aptarmy 8
  • OnEndpointFound/OnEndpointLost functions not working properly

    OnEndpointFound/OnEndpointLost functions not working properly

    void advertise(String name) async { try { bool ad = await Nearby().startAdvertising( name, strategy, onConnectionInitiated: onConnectionInit, onConnectionResult: (id, status) { print(status); }, onDisconnected: (id) { print("Disconnected: ${endpointMap[id]!.endpointName}, id $id"); }, serviceId: "com.test.app", ); print(ad); } catch (exception) { print(exception); } }

    void discover(String userName) async { bool connected=false; try { bool disc = await Nearby().startDiscovery( userName, strategy, onEndpointFound: (id, name, serviceId) { print("Id:" + id); print("Name:" +name); print("Service:" + serviceId); }, onEndpointLost: (id) { print("Lost discovered Endpoint: id $id"); }, serviceId: "com.test.app", ); print("DISCOVERING using : "+ userName +" "+ disc.toString()); print(strategy); } catch (e) { print(e); } }

    Everything is working fine but the function doesn't print the info above. Idk what's causing this to be honest. It only prints OnEndpointFound or OnEndpointLost in the console.

    image

    opened by VTapp1 7
  • how to Check no. of bytes send while sending the file

    how to Check no. of bytes send while sending the file

    hey ,

    i am unable to figure out how we can figure out no. of bytes sent . While receiving it works perfectly fine in accept connection();

    it appears its running on payloadtransfer update but not the one present in accept connection(); Thanks in advance.. errror

    opened by luciferamji 6
  • MissingPluginException

    MissingPluginException

    I'm getting this error when running the example:

    MissingPluginException(No implementation found for method startAdvertising on channel nearby_connections)

    Phone model: CLT-L29 EMUI: 10.0.0 Android: 10

    opened by kidandcat 5
  • Wondering about the required Bluetooth and location settings

    Wondering about the required Bluetooth and location settings

    Hey there, fantastic work getting this plugin up... (Got a project coming up that will really benefit from it)

    However, I'm wondering in that project I'll be working and targeting a number of users who while know about technology, if like to make implementing and using this tech very simple.

    For that case I'm wondering why is it that your plugin doesn't automatically handle the case of turning on the Bluetooth and location settings, performing the session then returning the device to it's original state; unlike how the native Connections API works?

    Or could I be mistaken that, that is how also the native API works?

    Thanks

    opened by TJMusiitwa 4
  • Transfers only via Bluetooth.

    Transfers only via Bluetooth.

    Hi, I've been using this plug-in for a while now, however it seems like it only transfers file over Bluetooth and not WiFi-Direct/Hotspot as Nearby connections should. Any views on this?

    opened by sokryptk 4
  • Error 8038: Unknown status code

    Error 8038: Unknown status code

    Title pretty much says it all. I'm getting this error when trying to initiate NFC on my pixel 6. Here's the full error:

    [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: PlatformException(Failure, 8038: unknown status code: 8038, null, null)
    E/flutter (12996): #0      StandardMethodCodec.decodeEnvelope
    package:flutter/…/services/message_codecs.dart:607
    E/flutter (12996): #1      MethodChannel._invokeMethod
    package:flutter/…/services/platform_channel.dart:177
    E/flutter (12996): <asynchronous suspension>
    E/flutter (12996): #2      Nearby.startAdvertising
    package:nearby_connections/src/nearby.dart:227
    
    opened by Jwiggiff 3
  • Feature Request: RSSI value

    Feature Request: RSSI value

    Please add a feature to calculate the rssi value of the discovered device. Or if there already is a solution to this here please point me towards it. Thank you.

    opened by faheem4797 3
  • compileSdkVersion is set to 28 - Causing Build error

    compileSdkVersion is set to 28 - Causing Build error

    Your compile version in your build.gradle for Android is set to "compileSdkVersion 28", causing compile errors:

    C:\dev\flutter\.pub-cache\hosted\pub.dartlang.org\nearby_connections-3.1.0\android\src\main\java\com\pkmnapps\nearby_connections\NearbyConnectionsPlugin.java:448: error: cannot find symbol
                    if (VERSION.SDK_INT < VERSION_CODES.Q
    ```)
    
    Can you fix?
    opened by SherwinJames 4
  • Support for Stream

    Support for Stream

    Finally having a relief - Support of Nearby for Flutter with no extra boilerplate efforts.

    Are we planning some way to support streaming? I wished to use the same with greatness of flutter.

    opened by vaishnavmhetre 1
  • Implement iOS side using MultipeerConnectivity

    Implement iOS side using MultipeerConnectivity

    Currently, this library supports only android to android communication.

    It is possible to add iOS to iOS communication to this plugin using the MultipeerConnectivity library for iOS Any help to achieve this will be appreciated.

    enhancement help wanted 
    opened by mannprerak2 3
Owner
Prerak Mann
Software Engineer | GSoC'20 @dart-lang | CSE @dtu
Prerak Mann
An HTTP file downloader packed with many features -> resumable downloads, multiple connections, buffering, auto-retry, etc.

An HTTP file downloader packed with many features -> resumable downloads, multiple connections, buffering, auto-retry, etc. Features Resumable downloa

Liu YuanYuan 4 Feb 2, 2022
A Flutter plugin for sharing files & text with other applications.

esys_flutter_share A Flutter plugin for sharing files & text with other applications. IMPORTANT Note for iOS If you are starting a new fresh app, you

ESYS GmbH 134 Sep 28, 2022
Tasawq App — Flutter framework and Firebase An application that objectives to display all nearby stores of all kinds and real estate.

Tasawq App — Flutter framework and Firebase An application that objectives to display all nearby stores of all kinds and real estate. Multi-vendor, standard user login to view nearby products and stores for rating, follow-up, messaging and more

null 1 Nov 10, 2022
A phone app that works as an offline lnurl-based point-of-sale.

LNURL-based Offline PoS app APK download: https://github.com/fiatjaf/lnurlpos-app/releases demo.mp4 Compatible with https://github.com/lnbits/lnbits-l

fiatjaf 16 Nov 23, 2022
Download files from Firebase Storage with Flutter. List all images, videos, or other files from Firebase and download them.

Flutter Tutorial - Download Files From Firebase Storage Download files from Firebase Storage with Flutter. List all images, videos, or other files fro

Johannes Milke 28 Dec 4, 2022
Upload Files To Firebase Storage with Flutter. Pick images, videos, or other files from your device and upload them to Firebase.

Flutter Tutorial - Upload Files To Firebase Storage Upload Files To Firebase Storage with Flutter. Pick images, videos, or other files from your devic

Johannes Milke 30 Dec 28, 2022
Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.

Flutter plugin that leverages Storage Access Framework (SAF) API to get access and perform the operations on files and folders.

Vehement 8 Nov 26, 2022
This is a university marketplace, where students buy and sell products and services online or offline. Mainly to connect the two parties together.

marktorder A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if th

Ibukunoluwa Naphtali 1 Jan 10, 2022
🌈 Repository for a compass project, basically an App for displaying bank transfers, with API requests, Flag persistence, Infinite Scroll, Error Handling, Unit Tests, Extract Sharing working with SOLID, BLoC and Designer Patterns.

?? Green Bank Aplicação desenvolvida em Flutter com intuito de trabalhar conexão com API, Gerenciamento de estado usando BLoC, Refatoração, Arquitetur

André Guerra Santos 28 Oct 7, 2022
WhereIsMoney - A money expense tracker with online and offline capabilities

WhereIsMoney ?? A money expense tracker to help you know where your money is goi

Junior Medehou 4 Feb 6, 2022
A lightweight and customizable http client that allows you to create offline-first dart app easily.

Enjoyable & customizable offline-first REST API client Unruffled is lightweight and customizable http client that allows you to create offline-first e

T. Milian 3 May 20, 2022
Bhagavad Gita app using flutter & Bhagavad-Gita-API is A lightweight Node.js based Bhagavad Gita API [An open source rest api on indian Vedic Scripture Shrimad Bhagavad Gita].

Gita Bhagavad Gita flutter app. Download App - Playstore Web Application About Bhagavad Gita app using flutter & Bhagavad-Gita-API is A lightweight No

Ravi Kovind 7 Apr 5, 2022
Flutter pos - A mobile POS written in Flutter, suitable for small cafe/restaurant, fully offline

Simple-POS A mobile POS written in Flutter, suitable for small cafe/restaurant,

Muhammed Basil E 7 Nov 2, 2022
(Flutter)Minimal App With Offline Storage(Using HIVE) Functionality.

TaskZ (Minimal + Offline TODO List App) Minimal App With Offline Storage(Using HIVE) Functionality. Getting Started ?? Any suggestion, improvement on

null 2 Oct 2, 2022
Wraps Flutter shared_preferences plugin, providing a iOS Suite Name support, it's helpful for sharing data from App to Widget.

shared_preferences_ios_sn Wraps Flutter shared_preferences plugin and provides an iOS Suite Name support, it's helpful for sharing data from App to iO

null 3 Sep 14, 2022
A flutter plugin for viewing PDF files in mobile app (Android & iOS)

PDF Viewer (JK) A flutter plugin for viewing PDF files in mobile app (Android & iOS) Pub.dev https://pub.dev/packages/pdf_viewer_jk Github ht

Jawad 8 Sep 30, 2021
A Flutter plugin to read 🔖 metadata of 🎵 media files. Supports Windows, Linux & Android.

flutter_media_metadata A Flutter plugin to read metadata of media files. A part of Harmonoid open source project ?? Install Add in your pubspec.yaml.

Harmonoid 60 Dec 2, 2022
Rajagiri connect is a networking platform that enables the students of Rajagiri to form a social network among themselves, enabling them to connect with their seniors, juniors and faculty for sharing of information and resources.

Rajagiri Connect Rajagiri connect is a networking platform that enables the students of Rajagiri to form a social network among themselves, enabling t

Muhammad Amaan 2 Nov 27, 2022
This plugin create a binding between your translations from .arb files and your Flutter app.

PROJECT MAINTENANCE PAUSED This project is no longer maintained due to the lack of time and availability. I'm a developer to and I know how frustratin

Razvan Lung 255 Dec 3, 2022