android_remote_pro 0.0.1 copy "android_remote_pro: ^0.0.1" to clipboard
android_remote_pro: ^0.0.1 copied to clipboard

A Flutter plugin to discover, pair, and control Android TV / Remote devices over Wi-Fi. Supports scanning, connecting, sending pairing codes, key events, and launching apps via deep links.

example/lib/main.dart

import 'dart:async';
import 'dart:io' show Platform;

import 'package:flutter/material.dart';
import 'package:android_remote_pro/android_remote_pro.dart';
import 'package:android_remote_pro/device.dart';
import 'package:android_remote_pro/key_codes.dart'; // <-- new helper

void main() => runApp(const MyApp());

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AndroidRemotePro? _androidPlugin;
  Device? _connectedDevice;
  final Map<String, Device> _devices = {};
  StreamSubscription? _scanSub;

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

    if (Platform.isAndroid) {
      _androidPlugin = AndroidRemotePro();
      _scanSub = _androidPlugin!.scanStream().listen(_onScanEvent, onError: (e) {
        debugPrint("⚠️ Scan error: $e");
      });
    } else if (Platform.isIOS) {
      debugPrint("📱 Running on iOS – implement RemoteTVManager");
    }
  }

  void _onScanEvent(dynamic raw) {
    if (raw == null) return;
    try {
      final obj = raw as Map;
      final event = obj['event'];

      if (event == 'found') {
        final deviceJsonStr = obj['device'] as String;
        final device = Device.fromJsonString(deviceJsonStr);
        setState(() => _devices[device.name] = device);
      } else if (event == 'removed') {
        final name = obj['name'] as String;
        setState(() => _devices.remove(name));
      }
    } catch (e) {
      debugPrint("❌ Failed to parse scan event: $e");
    }
  }

  @override
  void dispose() {
    _scanSub?.cancel();
    _androidPlugin?.stopScan();
    super.dispose();
  }

  Future<void> _startScan() async {
    if (Platform.isAndroid) {
      await _androidPlugin?.startScan();
    }
  }

  Future<void> _stopScan() async {
    if (Platform.isAndroid) {
      await _androidPlugin?.stopScan();
    }
  }

  Future<void> _connect(Device d) async {
    if (Platform.isAndroid) {
      await _androidPlugin?.connect(d.host, port: d.port);
      setState(() => _connectedDevice = d);
    }
  }

  Future<void> _sendKey(int keyCode) async {
    if (_connectedDevice != null) {
      await _androidPlugin?.sendKey(keyCode);
    } else {
      debugPrint("⚠️ No connected device");
    }
  }

  Widget _buildRemoteUI() {
    return Column(
      children: [
        const SizedBox(height: 12),
        Wrap(
          spacing: 12,
          runSpacing: 12,
          alignment: WrapAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.power),
              child: const Text("Power"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.volumeUp),
              child: const Text("Vol +"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.volumeDown),
              child: const Text("Vol -"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.mute),
              child: const Text("Mute"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.home),
              child: const Text("Home"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.back),
              child: const Text("Back"),
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.playPause),
              child: const Text("Play/Pause"),
            ),
          ],
        ),
        const SizedBox(height: 24),
        // D-Pad style arrows
        Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.dpadUp),
              child: const Icon(Icons.keyboard_arrow_up),
            ),
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                ElevatedButton(
                  onPressed: () => _sendKey(KeyCodes.dpadLeft),
                  child: const Icon(Icons.keyboard_arrow_left),
                ),
                ElevatedButton(
                  onPressed: () => _sendKey(KeyCodes.dpadCenter),
                  child: const Text("OK"),
                ),
                ElevatedButton(
                  onPressed: () => _sendKey(KeyCodes.dpadRight),
                  child: const Icon(Icons.keyboard_arrow_right),
                ),
              ],
            ),
            ElevatedButton(
              onPressed: () => _sendKey(KeyCodes.dpadDown),
              child: const Icon(Icons.keyboard_arrow_down),
            ),
          ],
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    final list = _devices.values.toList();

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Remote Pro — Cross Platform')),
        body: Column(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(onPressed: _startScan, child: const Text('Start Scan')),
                const SizedBox(width: 12),
                ElevatedButton(onPressed: _stopScan, child: const Text('Stop Scan')),
              ],
            ),
            Expanded(
              child: list.isEmpty
                  ? const Center(child: Text("No devices found"))
                  : ListView.builder(
                      itemCount: list.length,
                      itemBuilder: (ctx, idx) {
                        final d = list[idx];
                        return ListTile(
                          title: Text(d.name),
                          subtitle: Text("${d.host}:${d.port}"),
                          trailing: ElevatedButton(
                            onPressed: () => _connect(d),
                            child: const Text('Connect'),
                          ),
                        );
                      },
                    ),
            ),
            if (_connectedDevice != null)
              Padding(
                padding: const EdgeInsets.all(16),
                child: _buildRemoteUI(),
              ),
          ],
        ),
      ),
    );
  }
}
0
likes
130
points
21
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin to discover, pair, and control Android TV / Remote devices over Wi-Fi. Supports scanning, connecting, sending pairing codes, key events, and launching apps via deep links.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on android_remote_pro

Packages that implement android_remote_pro