ifp_detector 1.0.7
ifp_detector: ^1.0.7 copied to clipboard
Detect Interactive Flat Panels (IFPs) vs tablets on Android. Analyze screen size, brand, hardware features, and stylus support with confidence scoring for licensing and feature control.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ifp_detector/ifp_detector.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'IFP Detector Plugin Test',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'IFP Detector Plugin Test'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isLoading = false;
IfpDetectionResult? _detectionResult;
String? _errorMessage;
Future<void> _testPlugin() async {
setState(() {
_isLoading = true;
_errorMessage = null;
_detectionResult = null;
});
try {
// Test both methods
debugPrint('Testing simple isIfp() method...');
final isIFP = await IfpDetector.isIfp();
debugPrint('Simple result: $isIFP');
debugPrint('Testing detailed detectIfp() method...');
final result = await IfpDetector.detectIfp();
debugPrint('Detailed result: $result');
setState(() {
_detectionResult = result;
});
// Show a snackbar with the simple result
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Quick Result: ${isIFP ? "This is an IFP" : "This is a tablet"}',
),
backgroundColor: isIFP ? Colors.orange : Colors.green,
),
);
}
} on PlatformException catch (e) {
debugPrint('PlatformException: ${e.message}');
setState(() {
_errorMessage = "Plugin Error: ${e.message}";
});
} catch (e) {
debugPrint('Unexpected error: $e');
setState(() {
_errorMessage = "Unexpected error: $e";
});
} finally {
setState(() {
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('IFP Detector Plugin Test'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
const Icon(Icons.science, size: 48, color: Colors.blue),
const SizedBox(height: 12),
const Text(
'Plugin Functionality Test',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
const Text(
'This will test if the IFP Detector plugin is working correctly on your device.',
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey),
),
],
),
),
),
const SizedBox(height: 20),
ElevatedButton.icon(
onPressed: _isLoading ? null : _testPlugin,
icon: const Icon(Icons.play_arrow),
label: Text(_isLoading ? 'Testing Plugin...' : 'Test Plugin'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 16),
textStyle: const TextStyle(fontSize: 18),
),
),
const SizedBox(height: 20),
if (_isLoading)
const Center(
child: Column(
children: [
CircularProgressIndicator(),
SizedBox(height: 16),
Text('Running detection algorithms...'),
],
),
)
else if (_errorMessage != null)
Card(
color: Colors.red.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
const Icon(Icons.error, color: Colors.red, size: 48),
const SizedBox(height: 8),
const Text(
'Plugin Test Failed',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.red,
),
),
const SizedBox(height: 8),
Text(
_errorMessage!,
style: const TextStyle(color: Colors.red),
textAlign: TextAlign.center,
),
],
),
),
)
else if (_detectionResult != null)
Expanded(child: _buildSuccessCard())
else
const Expanded(
child: Center(
child: Text(
'Tap the button above to test the plugin',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
),
),
],
),
),
);
}
Widget _buildSuccessCard() {
final result = _detectionResult!;
return Expanded(
child: Card(
color: Colors.green.shade50,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(
Icons.check_circle,
color: Colors.green,
size: 32,
),
const SizedBox(width: 12),
const Expanded(
child: Text(
'Plugin Test Successful! β
',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
),
],
),
const SizedBox(height: 16),
const Text(
'Detection Results:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
_buildResultRow(
'Device Type',
result.isIFP
? 'Interactive Flat Panel (IFP)'
: 'Regular Tablet',
),
_buildResultRow(
'Confidence Level',
'${result.confidenceLevel} (${(result.confidenceScore * 100).toStringAsFixed(1)}%)',
),
const SizedBox(height: 8),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.amber.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.amber.shade200),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'π‘ What does Confidence Level mean?',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.amber,
),
),
const SizedBox(height: 6),
const Text(
'Confidence indicates how certain the algorithm is about the device classification:\n\n'
'β’ Very High (80-100%): Strong IFP indicators (20"+ screen, known IFP brand)\n'
'β’ High (60-79%): Good IFP evidence (large screen + stylus + display features)\n'
'β’ Medium (40-59%): Some IFP signs but inconclusive\n'
'β’ Low (20-39%): Weak IFP indicators, likely a tablet\n'
'β’ Very Low (0-19%): Strong tablet indicators (Samsung, Apple, etc.)\n\n'
'A 0% confidence for your tablet means the algorithm is very confident it\'s NOT an IFP!',
style: TextStyle(
fontSize: 12,
color: Colors.amber,
height: 1.3,
),
),
],
),
),
const SizedBox(height: 8),
_buildResultRow(
'Screen Size',
'${result.screenInches.toStringAsFixed(2)}" diagonal',
),
_buildResultRow('Screen Bucket', result.screenBucket),
_buildResultRow(
'Known IFP Brand',
result.matchedKnownIFPBrand ? 'Yes' : 'No',
),
_buildResultRow(
'HDMI CEC Support',
result.hasHdmiCec ? 'Yes' : 'No',
),
_buildResultRow(
'Leanback UI',
result.hasLeanback ? 'Yes' : 'No',
),
_buildResultRow(
'Stylus Support',
result.hasStylus ? 'Yes' : 'No',
),
_buildResultRow(
'Screen Size Reliable',
result.screenSizeReliable ? 'Yes' : 'No',
),
const SizedBox(height: 16),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.blue.shade200),
),
child: const Text(
'π The plugin is working perfectly! All detection methods executed successfully.',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.blue,
),
textAlign: TextAlign.center,
),
),
],
),
),
),
),
);
}
Widget _buildResultRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 140,
child: Text(
'$label:',
style: const TextStyle(fontWeight: FontWeight.w500),
),
),
Expanded(
child: Text(value, style: const TextStyle(color: Colors.grey)),
),
],
),
);
}
}