advanced_device_info 0.0.1
advanced_device_info: ^0.0.1 copied to clipboard
A Flutter plugin for comprehensive Android and iOS device information.
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:math';
import 'package:advanced_device_info/advanced_device_info.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Advanced Device Info',
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color(0xFF0F172A),
colorScheme: const ColorScheme.dark(
primary: Color(0xFF6366F1),
secondary: Color(0xFFEC4899),
surface: Color(0xFF1E293B),
),
appBarTheme: const AppBarTheme(
backgroundColor: Color(0xFF1E293B),
elevation: 0,
centerTitle: true,
),
cardTheme: CardThemeData(
color: const Color(0xFF1E293B),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 4,
),
),
home: const DashboardPage(),
);
}
}
class DashboardPage extends StatefulWidget {
const DashboardPage({super.key});
@override
State<DashboardPage> createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
bool _isLoading = true;
String? _errorMessage;
SystemInfo? _systemInfo;
@override
void initState() {
super.initState();
_fetchDeviceInfo();
}
Future<void> _fetchDeviceInfo() async {
setState(() {
_isLoading = true;
_errorMessage = null;
});
try {
final info = await AdvancedDeviceInfo.getSystemInfo();
setState(() {
_systemInfo = info;
_isLoading = false;
});
} catch (e) {
setState(() {
_errorMessage = e.toString();
_isLoading = false;
});
}
}
String _formatBytes(int bytes, {int decimals = 2}) {
if (bytes <= 0) return "0 B";
const suffixes = ["B", "KB", "MB", "GB", "TB"];
var i = (log(bytes) / log(1024)).floor();
return "${(bytes / pow(1024, i)).toStringAsFixed(decimals)} ${suffixes[i]}";
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
'DEVICE METRICS',
style: TextStyle(
fontWeight: FontWeight.w900,
letterSpacing: 2,
color: Colors.white,
),
),
actions: [
IconButton(
icon: const Icon(Icons.refresh, color: Colors.indigoAccent),
onPressed: _fetchDeviceInfo,
),
],
),
body: _isLoading
? const Center(
child: CircularProgressIndicator(
color: Color(0xFF6366F1),
),
)
: _errorMessage != null
? Center(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.error_outline, size: 64, color: Colors.redAccent),
const SizedBox(height: 16),
Text(
'Error loading device metrics:\n$_errorMessage',
textAlign: TextAlign.center,
style: const TextStyle(color: Colors.redAccent, fontSize: 16),
),
const SizedBox(height: 24),
ElevatedButton(
onPressed: _fetchDeviceInfo,
child: const Text('Try Again'),
),
],
),
),
)
: RefreshIndicator(
onRefresh: _fetchDeviceInfo,
color: const Color(0xFF6366F1),
child: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildHeaderCard(),
const SizedBox(height: 16),
_buildMetricsGrid(),
const SizedBox(height: 16),
_buildStorageCard(),
const SizedBox(height: 16),
_buildMemoryCard(),
const SizedBox(height: 16),
_buildBuildInfoCard(),
],
),
),
);
}
Widget _buildHeaderCard() {
final dev = _systemInfo!.deviceInfo;
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF6366F1), Color(0xFFEC4899)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(24),
boxShadow: [
BoxShadow(
color: const Color(0xFF6366F1).withAlpha(76),
blurRadius: 15,
offset: const Offset(0, 8),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
dev.deviceName,
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
if (dev.isEmulator)
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: Colors.black38,
borderRadius: BorderRadius.circular(20),
),
child: const Text(
'EMULATOR',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: Colors.amberAccent,
),
),
),
],
),
const SizedBox(height: 8),
Text(
'${dev.manufacturer.toUpperCase()} • ${dev.model}',
style: TextStyle(
fontSize: 14,
color: Colors.white.withAlpha(230),
fontWeight: FontWeight.w500,
letterSpacing: 0.5,
),
),
const SizedBox(height: 16),
Row(
children: [
const Icon(Icons.developer_mode, size: 16, color: Colors.white70),
const SizedBox(width: 8),
Text(
'Brand: ${dev.brand}',
style: const TextStyle(color: Colors.white70, fontSize: 13),
),
],
),
],
),
);
}
Widget _buildMetricsGrid() {
final cpu = _systemInfo!.cpuInfo;
final screen = _systemInfo!.screenInfo;
return Row(
children: [
Expanded(
child: _buildMetricCard(
title: 'CPU',
icon: Icons.memory, // cpu doesn't exist in standard Icons, we use memory
customIcon: const Icon(Icons.memory, color: Color(0xFF60A5FA), size: 32),
value: '${cpu.cores} Cores',
subtitle: cpu.architecture,
),
),
const SizedBox(width: 16),
Expanded(
child: _buildMetricCard(
title: 'DISPLAY',
customIcon: const Icon(Icons.screenshot, color: Color(0xFF34D399), size: 32),
value: '${screen.width} x ${screen.height}',
subtitle: '${screen.refreshRate.toInt()} Hz • @${screen.scale.toStringAsFixed(1)}x',
),
),
],
);
}
Widget _buildMetricCard({
required String title,
IconData? icon,
Widget? customIcon,
required String value,
required String subtitle,
}) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Colors.white54,
letterSpacing: 1.2,
),
),
customIcon ?? Icon(icon, color: Colors.blueAccent, size: 28),
],
),
const SizedBox(height: 16),
Text(
value,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: const TextStyle(
fontSize: 12,
color: Colors.white60,
),
),
],
),
),
);
}
Widget _buildStorageCard() {
final storage = _systemInfo!.storageInfo;
final usagePercent = storage.usagePercentage / 100.0;
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
Icon(Icons.storage, color: Colors.orangeAccent),
SizedBox(width: 8),
Text(
'STORAGE USAGE',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
),
),
],
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${storage.usagePercentage.toStringAsFixed(1)}% Used',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
'${_formatBytes(storage.usedStorage)} / ${_formatBytes(storage.totalStorage)}',
style: const TextStyle(fontSize: 13, color: Colors.white70),
),
],
),
const SizedBox(height: 10),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: LinearProgressIndicator(
value: usagePercent.clamp(0.0, 1.0),
minHeight: 12,
backgroundColor: const Color(0xFF334155),
valueColor: const AlwaysStoppedAnimation<Color>(Colors.orangeAccent),
),
),
const SizedBox(height: 8),
Text(
'Available storage space: ${_formatBytes(storage.freeStorage)}',
style: const TextStyle(fontSize: 12, color: Colors.white60),
),
],
),
),
);
}
Widget _buildMemoryCard() {
final memory = _systemInfo!.memoryInfo;
final usagePercent = memory.usagePercentage / 100.0;
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
Icon(Icons.developer_board, color: Colors.tealAccent),
SizedBox(width: 8),
Text(
'SYSTEM RAM',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
),
),
],
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'${memory.usagePercentage.toStringAsFixed(1)}% Used',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
'${_formatBytes(memory.usedRam)} / ${_formatBytes(memory.totalRam)}',
style: const TextStyle(fontSize: 13, color: Colors.white70),
),
],
),
const SizedBox(height: 10),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: LinearProgressIndicator(
value: usagePercent.clamp(0.0, 1.0),
minHeight: 12,
backgroundColor: const Color(0xFF334155),
valueColor: const AlwaysStoppedAnimation<Color>(Colors.tealAccent),
),
),
const SizedBox(height: 8),
Text(
'Available system memory: ${_formatBytes(memory.availableRam)}',
style: const TextStyle(fontSize: 12, color: Colors.white60),
),
],
),
),
);
}
Widget _buildBuildInfoCard() {
final dev = _systemInfo!.deviceInfo;
if (dev.buildInfo.isEmpty) return const SizedBox.shrink();
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Row(
children: [
Icon(Icons.settings_suggest, color: Colors.purpleAccent),
SizedBox(width: 8),
Text(
'DETAILED BUILD INFO',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
),
),
],
),
const SizedBox(height: 12),
const Divider(color: Colors.white12),
...dev.buildInfo.entries.map((entry) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Text(
entry.key,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white54,
fontSize: 13,
),
),
),
Expanded(
flex: 3,
child: Text(
entry.value?.toString() ?? 'N/A',
style: const TextStyle(
color: Colors.white,
fontSize: 13,
),
),
),
],
),
);
}),
],
),
),
);
}
}