最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

flutter - Regarding the issue of global monitoring of Bluetooth status navigation page - Stack Overflow

programmeradmin2浏览0评论

Flutter Version Flutter 3.24.3 • channel stable

How to continuously monitor the status of Bluetooth at the global level using the Flutter framework? No matter which page you are on, when you hear that Bluetooth is turned off, you will directly jump to the page where Bluetooth is turned off. Can this be achieved? If the current BuildContext instance is not obtained, there is no way to navigate. The navigatorKey property of MaterialApp cannot be used because the onGeneratedRoute property is not used. Is there any other way to achieve this requirement?

You can ignore the third-party plugin library. My problem now is that I cannot globally listen in Flutter and navigate to a new page based on the listening results, regardless of which page it is currently on. However, I cannot implement this (because the listener is not in the widget page) because I cannot obtain the context instance of the current page. This is because it is a global listening, not a specific page listening.

I have looked at the API of streamBuilder, and it reads streams and builds components. Can it only rely on widgets? Once the widget is relied upon, there will be a declaration cycle for the component. What I want is to globally monitor this state throughout the application and automatically redirect routes based on changes in state. Regarding the navigation routing method, the articles I found are all about navigating in widgets where there is a context context. Because the above requirements are globally monitored and not limited to the context of the current active page, it is impossible to obtain the latest context value.

Flutter Version Flutter 3.24.3 • channel stable

How to continuously monitor the status of Bluetooth at the global level using the Flutter framework? No matter which page you are on, when you hear that Bluetooth is turned off, you will directly jump to the page where Bluetooth is turned off. Can this be achieved? If the current BuildContext instance is not obtained, there is no way to navigate. The navigatorKey property of MaterialApp cannot be used because the onGeneratedRoute property is not used. Is there any other way to achieve this requirement?

You can ignore the third-party plugin library. My problem now is that I cannot globally listen in Flutter and navigate to a new page based on the listening results, regardless of which page it is currently on. However, I cannot implement this (because the listener is not in the widget page) because I cannot obtain the context instance of the current page. This is because it is a global listening, not a specific page listening.

I have looked at the API of streamBuilder, and it reads streams and builds components. Can it only rely on widgets? Once the widget is relied upon, there will be a declaration cycle for the component. What I want is to globally monitor this state throughout the application and automatically redirect routes based on changes in state. Regarding the navigation routing method, the articles I found are all about navigating in widgets where there is a context context. Because the above requirements are globally monitored and not limited to the context of the current active page, it is impossible to obtain the latest context value.

Share Improve this question asked Nov 19, 2024 at 13:25 dreamdream 134 bronze badges 15
  • What should be the behaviour when the app is closed or in background ? – Aks Commented Nov 20, 2024 at 12:21
  • If the application is closed, it naturally means it has ended, or if the application is running in the background, it should continue to run and listen. This question seems unrelated to the current issue, right – dream Commented Nov 26, 2024 at 1:51
  • Actually, this is related. Because In android there are 2 ways to listen broadcast receivers. one way you can always listen to changes event he app is closed, another way you can only listen when the app is running. So, for now I have working code for always listen changes and showing a Toast message. Let see if we can create your scenario. – Aks Commented Nov 26, 2024 at 3:44
  • Can the monitor automatically navigate to the specified page in the listener after hearing the status change? What I want is to globally monitor and push the navigation to a page where Bluetooth has been turned off after the Bluetooth connection is disconnected. On that page, you can request Bluetooth to be turned on, so there is no need to repeatedly add some judgments on each page. Because the global listener does not have a context object in the widget. – dream Commented Nov 26, 2024 at 11:29
  • you can navigate without context using a global key, the hard task is listening the bluetooth state. – Aks Commented Nov 26, 2024 at 12:09
 |  Show 10 more comments

1 Answer 1

Reset to default 0

Packages used:

  1. go_router
  2. bluetooth_manager

Note: You need to ask for bluetooth permission manually. For this example, I enabled the bluetooth permission for this app manually from device settings.

Add permission in AndroidManifest.xml

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

main.dart

import 'package:bt_navigate/bluetooth_service.dart';
import 'package:bt_navigate/router.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

void main() {
  GoRouter router = AppRouter.setupRouter();
  final BluetoothService bluetoothService = BluetoothService();
  
  //Global monitoring
  bluetoothService.getBluetoothStateStream().listen((event) {
    print("event received: $event");
    router.refresh();
  });
  runApp(MyApp(router: router));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key, required this.router});

  final GoRouter router;

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      debugShowCheckedModeBanner: false,
      routeInformationParser: router.routeInformationParser,
      routeInformationProvider: router.routeInformationProvider,
      routerDelegate: router.routerDelegate,
      theme: ThemeData(useMaterial3: false),
    );
  }
}

router.dart

import 'package:bt_navigate/bluetooth_service.dart';
import 'package:bt_navigate/screens/bluetooth_off_screen.dart';
import 'package:bt_navigate/screens/home_page.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

class AppRouter {
  static GoRouter setupRouter() {
    const String homeRoute = "/";
    const String bluetoothOffRoute = "/bluetooth_off";

    final BluetoothService bluetoothService = BluetoothService();

    return GoRouter(
      initialLocation: homeRoute,
      routes: [
        GoRoute(
          path: homeRoute,
          pageBuilder: (context, state) {
            return const MaterialPage(child: HomePage());
          },
        ),
        GoRoute(
          path: bluetoothOffRoute,
          pageBuilder: (context, state) {
            return const MaterialPage(child: BluetoothOffScreen());
          },
        ),
      ],
      redirect: (context, state) async {
        // Check the Bluetooth status
        final isBluetoothOn = await bluetoothService.isBluetoothOn();

        // Define paths
        final bool onBluetoothPage = state.matchedLocation == bluetoothOffRoute;
        // final bool onHomePage = state.matchedLocation == "/";

        // Redirect logic
        if (!isBluetoothOn) {
          return bluetoothOffRoute; // Navigate to a Bluetooth-disabled page
        }
        if (onBluetoothPage && isBluetoothOn) {
          return homeRoute; // Navigate to the home page
        }
        return null; // No redirection
      },
    );
  }
}

bluetooth_service.dart

import 'package:bluetooth_manager/bluetooth_manager.dart';
import 'package:bluetooth_manager/models/bluetooth_models.dart';

class BluetoothService {
  // Private constructor
  BluetoothService._privateConstructor();

  // Singleton instance
  static final BluetoothService _instance = BluetoothService._privateConstructor();

  // Factory constructor to return the same instance
  factory BluetoothService() {
    return _instance;
  }

  // BluetoothManager instance
  final BluetoothManager bluetoothManager = BluetoothManager();

  // Method to get the current Bluetooth state
  Future<bool> isBluetoothOn() async {
    final state = await bluetoothManager.getBluetoothState();
    return state == BluetoothState.on;
  }

  // Stream to listen to Bluetooth state changes
  Stream<BluetoothState> getBluetoothStateStream() {
    return bluetoothManager.getBluetoothStateStream();
  }
}

homepage.dart

import 'package:bt_navigate/bluetooth_service.dart';
import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final BluetoothService bluetoothService = BluetoothService();

  @override
  void initState() {
    super.initState();
  }

  Future<bool> getBluetoothStatus() async {
    return await bluetoothService.isBluetoothOn();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Colors.green,),
      body: SafeArea(
          child: Center(
              child: FutureBuilder(
        future: getBluetoothStatus(),
        builder: (context, snapshot) {
          return Text("status: ${snapshot.data}");
        },
      ))),
    );
  }
}

bluetooth_off_screen.dart

import 'package:flutter/material.dart';

class BluetoothOffScreen extends StatefulWidget {
  const BluetoothOffScreen({super.key});

  @override
  State<BluetoothOffScreen> createState() => _BluetoothOffScreenState();
}

class _BluetoothOffScreenState extends State<BluetoothOffScreen> {
  @override
  Widget build(BuildContext context) {
    return  Scaffold(
            appBar: AppBar(backgroundColor: Colors.red,),
      body: const Center(child: Text("Bluetooth status off")),
    );
  }
}

Output

发布评论

评论列表(0)

  1. 暂无评论