torch_flashlight 0.0.3
torch_flashlight: ^0.0.3 copied to clipboard
A Flutter plugin for controlling torch/flashlight availability, state, blinking, SOS, brightness, and background operation.
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:torch_flashlight/torch_flashlight.dart';
void main() {
runApp(const TorchApp());
}
class TorchApp extends StatelessWidget {
const TorchApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Torch Flashlight Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.amber),
useMaterial3: true,
),
home: const MainScreen(),
);
}
}
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
final TorchController _controller = TorchController();
bool _isTorchOn = false;
bool _isTorchAvailable = false;
bool _isLoading = true;
TorchCapabilities? _capabilities;
FlashMode _selectedFlashMode = FlashMode.torch;
int _strength = 0;
int _maxStrength = 0;
StreamSubscription<bool>? _torchStateSubscription;
@override
void initState() {
super.initState();
_initializeTorch();
}
Future<void> _initializeTorch() async {
final available = await _controller.isAvailable();
final capabilities = await _controller.getCapabilities();
final maxStrength = await _controller.getMaxStrength();
setState(() {
_isTorchAvailable = available;
_capabilities = capabilities;
_maxStrength = maxStrength;
_isLoading = false;
});
// Listen to torch state changes
_torchStateSubscription = _controller.torchStream.listen((isOn) {
if (mounted) {
setState(() {
_isTorchOn = isOn;
});
}
});
}
@override
void dispose() {
_torchStateSubscription?.cancel();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Torch Flashlight Demo'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: !_isTorchAvailable
? const Center(child: Text('No torch available on this device'))
: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildTorchStatusCard(),
const SizedBox(height: 16),
_buildCapabilitiesCard(),
const SizedBox(height: 16),
_buildBasicControlsCard(),
const SizedBox(height: 16),
_buildFlashModeCard(),
const SizedBox(height: 16),
_buildStrengthControlCard(),
const SizedBox(height: 16),
_buildBlinkingCard(),
const SizedBox(height: 16),
_buildSOSCard(),
const SizedBox(height: 16),
_buildFadeCard(),
const SizedBox(height: 16),
_buildBackgroundCard(),
const SizedBox(height: 16),
_buildNativeBlinkCard(),
],
),
),
);
}
Widget _buildTorchStatusCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Icon(
_isTorchOn ? Icons.flashlight_on : Icons.flashlight_off,
size: 80,
color: _isTorchOn ? Colors.amber : Colors.grey,
),
const SizedBox(height: 16),
Text(
_isTorchOn ? 'Torch is ON' : 'Torch is OFF',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 16),
ElevatedButton.icon(
onPressed: _toggleTorch,
icon: Icon(_isTorchOn ? Icons.flash_off : Icons.flash_on),
label: Text(_isTorchOn ? 'Turn Off' : 'Turn On'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: _isTorchOn ? Colors.red : Colors.green,
),
),
],
),
),
);
}
Widget _buildCapabilitiesCard() {
if (_capabilities == null) return const SizedBox.shrink();
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Device Capabilities',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
_buildCapabilityRow(
'Strength Control', _capabilities!.supportsStrength),
_buildCapabilityRow('Blinking', _capabilities!.supportsBlinking),
_buildCapabilityRow(
'Background Operation', _capabilities!.supportsBackground),
_buildCapabilityRow('Fade Effects', _capabilities!.supportsFade),
_buildCapabilityRow('SOS Mode', _capabilities!.supportsSOS),
_buildCapabilityRow(
'Custom Blink', _capabilities!.supportsCustomBlink),
],
),
),
);
}
Widget _buildCapabilityRow(String label, bool supported) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
Icon(
supported ? Icons.check_circle : Icons.cancel,
color: supported ? Colors.green : Colors.red,
size: 20,
),
const SizedBox(width: 8),
Text(label),
],
),
);
}
Widget _buildBasicControlsCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Basic Controls',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: _enable,
icon: const Icon(Icons.play_arrow),
label: const Text('Enable'),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton.icon(
onPressed: _disable,
icon: const Icon(Icons.stop),
label: const Text('Disable'),
),
),
],
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _toggle,
icon: const Icon(Icons.swap_horiz),
label: const Text('Toggle'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
),
),
],
),
),
);
}
Widget _buildFlashModeCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Flash Mode',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
SegmentedButton<FlashMode>(
segments: const [
ButtonSegment(
value: FlashMode.torch,
label: Text('Torch'),
icon: Icon(Icons.flashlight_on),
),
ButtonSegment(
value: FlashMode.flash,
label: Text('Flash'),
icon: Icon(Icons.bolt),
),
],
selected: {_selectedFlashMode},
onSelectionChanged: (Set<FlashMode> newSelection) {
setState(() {
_selectedFlashMode = newSelection.first;
});
},
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () => _enableWithMode(_selectedFlashMode),
icon: const Icon(Icons.play_arrow),
label: Text('Enable with ${_selectedFlashMode.name} mode'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
),
),
],
),
),
);
}
Widget _buildStrengthControlCard() {
if (_capabilities == null || !_capabilities!.supportsStrength) {
return const SizedBox.shrink();
}
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Strength Control',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Text('Current: $_strength / Max: $_maxStrength'),
const SizedBox(height: 12),
Slider(
value: _strength.toDouble(),
max: _maxStrength.toDouble(),
divisions: _maxStrength > 0 ? _maxStrength : 1,
label: _strength.toString(),
onChanged: (value) {
setState(() {
_strength = value.toInt();
});
},
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: () => _setStrength(_strength),
icon: const Icon(Icons.tune),
label: const Text('Set Strength'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
),
),
],
),
),
);
}
Widget _buildBlinkingCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Blinking',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () => _startBlinking(500),
icon: const Icon(Icons.play_arrow),
label: const Text('Blink 500ms'),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton.icon(
onPressed: () => _startBlinking(1000),
icon: const Icon(Icons.play_arrow),
label: const Text('Blink 1s'),
),
),
],
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _stopBlinking,
icon: const Icon(Icons.stop),
label: const Text('Stop Blinking'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: Colors.red,
),
),
],
),
),
);
}
Widget _buildSOSCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'SOS Mode',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: _startSOS,
icon: const Icon(Icons.sos),
label: const Text('Start SOS'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: Colors.orange,
),
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _stopSOS,
icon: const Icon(Icons.stop),
label: const Text('Stop SOS'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: Colors.red,
),
),
],
),
),
);
}
Widget _buildFadeCard() {
if (_capabilities == null || !_capabilities!.supportsFade) {
return const SizedBox.shrink();
}
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Fade Effects',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: _fadeIn,
icon: const Icon(Icons.arrow_upward),
label: const Text('Fade In'),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton.icon(
onPressed: _fadeOut,
icon: const Icon(Icons.arrow_downward),
label: const Text('Fade Out'),
),
),
],
),
],
),
),
);
}
Widget _buildBackgroundCard() {
if (_capabilities == null || !_capabilities!.supportsBackground) {
return const SizedBox.shrink();
}
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Background Execution',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
ElevatedButton.icon(
onPressed: _startForegroundService,
icon: const Icon(Icons.play_arrow),
label: const Text('Start Foreground Service'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
),
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _stopForegroundService,
icon: const Icon(Icons.stop),
label: const Text('Stop Foreground Service'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: Colors.red,
),
),
],
),
),
);
}
Widget _buildNativeBlinkCard() {
return Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Native Blinking (Better Performance)',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () => _startNativeBlink(300),
icon: const Icon(Icons.play_arrow),
label: const Text('300ms'),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton.icon(
onPressed: () => _startNativeBlink(500),
icon: const Icon(Icons.play_arrow),
label: const Text('500ms'),
),
),
],
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _stopNativeBlink,
icon: const Icon(Icons.stop),
label: const Text('Stop Native Blink'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(double.infinity, 48),
backgroundColor: Colors.red,
),
),
],
),
),
);
}
// Action methods
Future<void> _toggleTorch() async {
try {
await _controller.toggle();
} catch (e) {
_showError('Failed to toggle torch: $e');
}
}
Future<void> _enable() async {
try {
await _controller.enable();
} catch (e) {
_showError('Failed to enable torch: $e');
}
}
Future<void> _disable() async {
try {
await _controller.disable();
} catch (e) {
_showError('Failed to disable torch: $e');
}
}
Future<void> _toggle() async {
try {
await _controller.toggle();
} catch (e) {
_showError('Failed to toggle torch: $e');
}
}
Future<void> _enableWithMode(FlashMode mode) async {
try {
await _controller.enable(mode: mode);
} catch (e) {
_showError('Failed to enable torch: $e');
}
}
Future<void> _setStrength(int strength) async {
try {
await _controller.setStrength(strength);
_showMessage('Strength set to $strength');
} catch (e) {
_showError('Failed to set strength: $e');
}
}
Future<void> _startBlinking(int interval) async {
try {
// Use custom blink pattern for simple blinking
final pattern = [interval, interval]; // on/off pattern
await _controller.startCustomBlink(pattern);
_showMessage('Blinking started (${interval}ms interval)');
} catch (e) {
_showError('Failed to start blinking: $e');
}
}
Future<void> _stopBlinking() async {
try {
await _controller.stopCustomBlink();
_showMessage('Blinking stopped');
} catch (e) {
_showError('Failed to stop blinking: $e');
}
}
Future<void> _startSOS() async {
try {
await _controller.startSOS();
_showMessage('SOS mode started');
} catch (e) {
_showError('Failed to start SOS: $e');
}
}
Future<void> _stopSOS() async {
try {
await _controller.stopSOS();
_showMessage('SOS mode stopped');
} catch (e) {
_showError('Failed to stop SOS: $e');
}
}
Future<void> _fadeIn() async {
try {
await _controller.fadeIn();
_showMessage('Fade in started');
} catch (e) {
_showError('Failed to fade in: $e');
}
}
Future<void> _fadeOut() async {
try {
await _controller.fadeOut();
_showMessage('Fade out started');
} catch (e) {
_showError('Failed to fade out: $e');
}
}
Future<void> _startForegroundService() async {
try {
await _controller.startForegroundService();
_showMessage('Foreground service started');
} catch (e) {
_showError('Failed to start foreground service: $e');
}
}
Future<void> _stopForegroundService() async {
try {
await _controller.stopForegroundService();
_showMessage('Foreground service stopped');
} catch (e) {
_showError('Failed to stop foreground service: $e');
}
}
Future<void> _startNativeBlink(int interval) async {
try {
await _controller.startNativeBlink(interval);
_showMessage('Native blinking started (${interval}ms interval)');
} catch (e) {
_showError('Failed to start native blinking: $e');
}
}
Future<void> _stopNativeBlink() async {
try {
await _controller.stopNativeBlink();
_showMessage('Native blinking stopped');
} catch (e) {
_showError('Failed to stop native blinking: $e');
}
}
void _showMessage(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), backgroundColor: Colors.green),
);
}
void _showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message), backgroundColor: Colors.red),
);
}
}