ios_device_monitor 0.1.0 copy "ios_device_monitor: ^0.1.0" to clipboard
ios_device_monitor: ^0.1.0 copied to clipboard

PlatformiOS

Comprehensive iOS device monitoring plugin with CPU, GPU, thermal, uptime, and advanced CPU usage tracking.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
import 'package:ios_device_monitor/ios_device_monitor.dart';
import 'package:ios_device_monitor/models/models.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'iOS Device Monitor',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.light,
        ),
        cardTheme: CardThemeData(
          elevation: 2,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.dark,
        ),
        cardTheme: CardThemeData(
          elevation: 2,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16),
          ),
        ),
      ),
      home: const DeviceMonitorScreen(),
    );
  }
}

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

  @override
  State<DeviceMonitorScreen> createState() => _DeviceMonitorScreenState();
}

class _DeviceMonitorScreenState extends State<DeviceMonitorScreen> {
  CpuInfo? _cpuInfo;
  GpuInfo? _gpuInfo;
  ThermalState? _thermalState;
  SystemUptime? _systemUptime;
  AdvancedCpuUsage? _advancedCpuUsage;

  bool _isLoading = false;
  String? _errorMessage;

  Timer? _refreshTimer;

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

  @override
  void dispose() {
    _refreshTimer?.cancel();
    super.dispose();
  }

  Future<void> _loadAllData() async {
    if (_isLoading) return;

    setState(() {
      _isLoading = true;
      _errorMessage = null;
    });

    try {
      final results = await Future.wait([
        IosDeviceMonitor.getCpuInfo(),
        IosDeviceMonitor.getGpuInfo(),
        IosDeviceMonitor.getThermalState(),
        IosDeviceMonitor.getSystemUptime(),
        IosDeviceMonitor.getAdvancedCpuUsage(),
      ]);

      setState(() {
        _cpuInfo = results[0] as CpuInfo;
        _gpuInfo = results[1] as GpuInfo;
        _thermalState = results[2] as ThermalState;
        _systemUptime = results[3] as SystemUptime;
        _advancedCpuUsage = results[4] as AdvancedCpuUsage;
        _isLoading = false;
      });
    } on PlatformException catch (e) {
      setState(() {
        _errorMessage = 'Platform Error: ${e.message}';
        _isLoading = false;
      });
    } catch (e) {
      setState(() {
        _errorMessage = 'Error: $e';
        _isLoading = false;
      });
    }
  }

  Future<void> _refreshCpuUsage() async {
    try {
      final cpuUsage = await IosDeviceMonitor.getAdvancedCpuUsage();
      setState(() {
        _advancedCpuUsage = cpuUsage;
      });
    } catch (e) {
      debugPrint('Failed to refresh CPU usage: $e');
    }
  }

  void _toggleAutoRefresh() {
    setState(() {
      if (_refreshTimer != null) {
        _refreshTimer?.cancel();
        _refreshTimer = null;
      } else {
        _refreshTimer = Timer.periodic(
          const Duration(seconds: 2),
          (_) => _refreshCpuUsage(),
        );
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    final colorScheme = Theme.of(context).colorScheme;

    return Scaffold(
      floatingActionButton: FloatingActionButton(onPressed: () {
        debugPrint('cpu');
        debugPrint(_cpuInfo?.architecture.toString());
        debugPrint(_cpuInfo?.coreCount.toString());
        debugPrint(_cpuInfo?.coreCountDescription.toString());
        debugPrint('\n\n\ngpu');
        debugPrint(_gpuInfo?.maxThreadsPerThreadgroup.toString());
        debugPrint(_gpuInfo?.name.toString());
        debugPrint(_gpuInfo?.recommendedMaxWorkingSetSize.toString());
        debugPrint(_gpuInfo?.registryID.toString());
        debugPrint(_gpuInfo?.supportedFeatures.toString());
        debugPrint(_gpuInfo?.supportsFamily.toString());
        debugPrint('\n\n\ntemperature');
        debugPrint(_thermalState?.description.toString());
        debugPrint(_thermalState?.isCritical.toString());
        debugPrint(_thermalState?.isThrottling.toString());
        debugPrint(_thermalState?.isWarning.toString());
        debugPrint(_thermalState?.level.toString());
        debugPrint(_thermalState?.state.toString());
        debugPrint(_thermalState?.statusMessage.toString());
        debugPrint(_thermalState?.thermalLevel.toString());
        debugPrint('\n\n\nsystemup time');
        debugPrint(_systemUptime?.bootDate.toString());
        debugPrint(_systemUptime?.bootDateFormatted.toString());
        debugPrint(_systemUptime?.bootTime.toString());
        debugPrint(_systemUptime?.hasBeenRunningForADay.toString());
        debugPrint(_systemUptime?.hasBeenRunningForAWeek.toString());
        debugPrint(_systemUptime?.shortUptimeDescription.toString());
        debugPrint(_systemUptime?.uptime.toString());
        debugPrint(_systemUptime?.uptimeDays.toString());
        debugPrint(_systemUptime?.uptimeFormatted.toString());
        debugPrint(_systemUptime?.uptimeHours.toString());
        debugPrint('\n\n\nadvanced');
        debugPrint(_advancedCpuUsage?.activeThreadCount.toString());
        debugPrint(_advancedCpuUsage?.averageCoreUsage.toString());
        debugPrint(_advancedCpuUsage?.coreCount.toString());
        debugPrint(_advancedCpuUsage?.detailedCoreUsages.toString());
        debugPrint(_advancedCpuUsage?.isHighUsage.toString());
        debugPrint(_advancedCpuUsage?.isLowUsage.toString());
        debugPrint(_advancedCpuUsage?.isMediumUsage.toString());
        debugPrint(_advancedCpuUsage?.systemTime.toString());
        debugPrint(_advancedCpuUsage?.threadDetails.toString());
        debugPrint(_advancedCpuUsage?.timestamp.toString());
        debugPrint(_advancedCpuUsage?.timestampDate.toString());
        debugPrint(_advancedCpuUsage?.timestampFormatted.toString());
        debugPrint(_advancedCpuUsage?.totalThreadCount.toString());
        debugPrint(_advancedCpuUsage?.totalTime.toString());
        debugPrint(_advancedCpuUsage?.usage.toString());
        debugPrint(_advancedCpuUsage?.usageLevel.toString());
        debugPrint(_advancedCpuUsage?.usagePercentageString.toString());
        debugPrint(_advancedCpuUsage?.userTime.toString());
      }),
      appBar: AppBar(
        title: const Text('iOS Device Monitor'),
        centerTitle: true,
        elevation: 0,
        backgroundColor: colorScheme.surface,
        foregroundColor: colorScheme.onSurface,
        actions: [
          IconButton(
            icon: Icon(_refreshTimer != null ? Icons.pause : Icons.play_arrow),
            tooltip: _refreshTimer != null
                ? 'Stop Auto-Refresh'
                : 'Start Auto-Refresh',
            onPressed: _advancedCpuUsage != null ? _toggleAutoRefresh : null,
          ),
        ],
      ),
      body: RefreshIndicator(
        onRefresh: _loadAllData,
        child: _buildBody(context, colorScheme),
      ),
    );
  }

  Widget _buildBody(BuildContext context, ColorScheme colorScheme) {
    if (_isLoading && _cpuInfo == null) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(
              color: colorScheme.primary,
            ),
            const SizedBox(height: 16),
            Text(
              'Loading device information...',
              style: TextStyle(
                color: colorScheme.onSurface.withValues(alpha: 0.7),
              ),
            ),
          ],
        ),
      );
    }

    if (_errorMessage != null && _cpuInfo == null) {
      return Center(
        child: Padding(
          padding: const EdgeInsets.all(24.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Icon(
                Icons.error_outline,
                size: 64,
                color: colorScheme.error,
              ),
              const SizedBox(height: 16),
              Text(
                'Failed to Load Data',
                style: Theme.of(context).textTheme.headlineSmall?.copyWith(
                      color: colorScheme.error,
                    ),
              ),
              const SizedBox(height: 8),
              Text(
                _errorMessage!,
                textAlign: TextAlign.center,
                style: TextStyle(
                  color: colorScheme.onSurface.withValues(alpha: 0.7),
                ),
              ),
              const SizedBox(height: 24),
              FilledButton.icon(
                onPressed: _loadAllData,
                icon: const Icon(Icons.refresh),
                label: const Text('Retry'),
              ),
            ],
          ),
        ),
      );
    }

    return ListView(
      padding: const EdgeInsets.all(16.0),
      children: [
        _buildCpuInfoSection(colorScheme),
        const SizedBox(height: 16),
        _buildGpuInfoSection(colorScheme),
        const SizedBox(height: 16),
        _buildThermalStateSection(colorScheme),
        const SizedBox(height: 16),
        _buildSystemUptimeSection(colorScheme),
        const SizedBox(height: 16),
        _buildAdvancedCpuUsageSection(colorScheme),
        const SizedBox(height: 16),
        Center(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Text(
              'Pull down to refresh all data',
              style: TextStyle(
                color: colorScheme.onSurface.withValues(alpha: 0.5),
                fontSize: 12,
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget _buildCpuInfoSection(ColorScheme colorScheme) {
    if (_cpuInfo == null) return const SizedBox.shrink();

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.memory,
                  color: colorScheme.primary,
                  size: 28,
                ),
                const SizedBox(width: 12),
                Text(
                  'CPU Information',
                  style: Theme.of(context).textTheme.titleLarge?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                ),
              ],
            ),
            const Divider(height: 24),
            _buildInfoRow(
              'Architecture',
              _cpuInfo!.architecture ?? 'Unknown',
              Icons.architecture,
              colorScheme,
            ),
            _buildInfoRow(
              'Core Count',
              _formatCoreCount(_cpuInfo!.coreCountDescription),
              Icons.grid_view,
              colorScheme,
            ),
            if (_cpuInfo!.architecture?.toLowerCase().contains('arm64') ??
                false)
              Padding(
                padding: const EdgeInsets.only(top: 12.0),
                child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                  decoration: BoxDecoration(
                    color: colorScheme.primaryContainer,
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Icon(
                        Icons.apple,
                        size: 16,
                        color: colorScheme.onPrimaryContainer,
                      ),
                      const SizedBox(width: 6),
                      Text(
                        'Apple Silicon',
                        style: TextStyle(
                          color: colorScheme.onPrimaryContainer,
                          fontWeight: FontWeight.w600,
                          fontSize: 12,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildGpuInfoSection(ColorScheme colorScheme) {
    if (_gpuInfo == null) return const SizedBox.shrink();

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.videogame_asset,
                  color: colorScheme.secondary,
                  size: 28,
                ),
                const SizedBox(width: 12),
                Text(
                  'GPU Information',
                  style: Theme.of(context).textTheme.titleLarge?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                ),
              ],
            ),
            const Divider(height: 24),
            _buildInfoRow(
              'GPU Name',
              _gpuInfo!.name,
              Icons.label,
              colorScheme,
            ),
            if (_formatBytes(_gpuInfo!.recommendedMaxWorkingSetSize) != null)
              _buildInfoRow(
                'Max Working Set',
                _formatBytes(_gpuInfo!.registryID)!,
                Icons.storage,
                colorScheme,
              ),
            if (_gpuInfo!.registryID != null)
              _buildInfoRow(
                'Registry ID',
                '${_gpuInfo!.registryID}',
                Icons.fingerprint,
                colorScheme,
              ),
            if (_gpuInfo!.maxThreadsPerThreadgroup != null)
              _buildInfoRow(
                'Max Threads/Group',
                '${_gpuInfo!.maxThreadsPerThreadgroup!.width}×'
                    '${_gpuInfo!.maxThreadsPerThreadgroup!.height}×'
                    '${_gpuInfo!.maxThreadsPerThreadgroup!.depth}',
                Icons.apps,
                colorScheme,
              ),
            if (_gpuInfo!.supportedFeatures.isNotEmpty) ...[
              const SizedBox(height: 12),
              Text(
                'Metal GPU Families',
                style: Theme.of(context).textTheme.labelLarge?.copyWith(
                      color: colorScheme.onSurface.withValues(alpha: 0.7),
                    ),
              ),
              const SizedBox(height: 8),
              Wrap(
                spacing: 8,
                runSpacing: 8,
                children: _gpuInfo!.supportedFeatures.map((feature) {
                  return Chip(
                    label: Text(
                      feature,
                      style: TextStyle(
                        fontSize: 11,
                        color: colorScheme.onSecondaryContainer,
                      ),
                    ),
                    backgroundColor: colorScheme.secondaryContainer,
                    padding: EdgeInsets.zero,
                    visualDensity: VisualDensity.compact,
                  );
                }).toList(),
              ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildThermalStateSection(ColorScheme colorScheme) {
    if (_thermalState == null) return const SizedBox.shrink();

    Color thermalColor;
    IconData thermalIcon;

    if (_thermalState!.isCritical) {
      thermalColor = Colors.red;
      thermalIcon = Icons.whatshot;
    } else if (_thermalState!.isWarning) {
      thermalColor = Colors.orange;
      thermalIcon = Icons.warning_amber;
    } else {
      thermalColor = Colors.green;
      thermalIcon = Icons.check_circle;
    }

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.thermostat,
                  color: colorScheme.tertiary,
                  size: 28,
                ),
                const SizedBox(width: 12),
                Text(
                  'Thermal State',
                  style: Theme.of(context).textTheme.titleLarge?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                ),
              ],
            ),
            const Divider(height: 24),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: thermalColor.withValues(alpha: 0.1),
                borderRadius: BorderRadius.circular(12),
                border: Border.all(
                  color: thermalColor.withValues(alpha: 0.3),
                  width: 2,
                ),
              ),
              child: Row(
                children: [
                  Icon(
                    thermalIcon,
                    color: thermalColor,
                    size: 48,
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          _thermalState!.statusMessage ?? _thermalState!.state,
                          style: Theme.of(context)
                              .textTheme
                              .headlineSmall
                              ?.copyWith(
                                color: thermalColor,
                                fontWeight: FontWeight.bold,
                              ),
                        ),
                        const SizedBox(height: 4),
                        Text(
                          _thermalState!.description ??
                              'No description available',
                          style: TextStyle(
                            color: colorScheme.onSurface.withValues(alpha: 0.7),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 16),
            _buildInfoRow(
              'Thermal State',
              _thermalState!.state,
              Icons.info_outline,
              colorScheme,
            ),
            _buildInfoRow(
              'Level',
              '${_thermalState!.level}',
              Icons.layers,
              colorScheme,
            ),
            _buildInfoRow(
              'Throttling',
              _thermalState!.isThrottling ? 'Yes' : 'No',
              _thermalState!.isThrottling
                  ? Icons.speed
                  : Icons.check_circle_outline,
              colorScheme,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSystemUptimeSection(ColorScheme colorScheme) {
    if (_systemUptime == null) return const SizedBox.shrink();

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.access_time,
                  color: colorScheme.primary,
                  size: 28,
                ),
                const SizedBox(width: 12),
                Text(
                  'System Uptime',
                  style: Theme.of(context).textTheme.titleLarge?.copyWith(
                        fontWeight: FontWeight.bold,
                      ),
                ),
              ],
            ),
            const Divider(height: 24),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: colorScheme.primaryContainer.withValues(alpha: 0.3),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Row(
                children: [
                  Icon(
                    Icons.timer,
                    color: colorScheme.primary,
                    size: 48,
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          _systemUptime!.uptimeFormatted,
                          style: Theme.of(context)
                              .textTheme
                              .headlineSmall
                              ?.copyWith(
                                color: colorScheme.onSurface,
                                fontWeight: FontWeight.bold,
                              ),
                        ),
                        const SizedBox(height: 4),
                        Text(
                          _systemUptime!.shortUptimeDescription,
                          style: TextStyle(
                            color: colorScheme.onSurface.withValues(alpha: 0.7),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 16),
            _buildInfoRow(
              'Boot Date',
              _systemUptime!.bootDateFormatted,
              Icons.calendar_today,
              colorScheme,
            ),
            _buildInfoRow(
              'Uptime (seconds)',
              '${_systemUptime!.uptime.toStringAsFixed(0)}s',
              Icons.hourglass_bottom,
              colorScheme,
            ),
            _buildInfoRow(
              'Uptime (hours)',
              '${_systemUptime!.uptimeHours.toStringAsFixed(2)}h',
              Icons.schedule,
              colorScheme,
            ),
            _buildInfoRow(
              'Uptime (days)',
              '${_systemUptime!.uptimeDays.toStringAsFixed(2)} days',
              Icons.event,
              colorScheme,
            ),
            if (_systemUptime!.hasBeenRunningForAWeek)
              Padding(
                padding: const EdgeInsets.only(top: 12.0),
                child: Container(
                  padding:
                      const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                  decoration: BoxDecoration(
                    color: Colors.amber.withValues(alpha: 0.2),
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(
                      color: Colors.amber,
                      width: 1,
                    ),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Icon(
                        Icons.battery_alert,
                        size: 16,
                        color: Colors.amber,
                      ),
                      const SizedBox(width: 6),
                      Text(
                        'Consider restarting your device',
                        style: TextStyle(
                          color: colorScheme.onSurface,
                          fontWeight: FontWeight.w600,
                          fontSize: 12,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildAdvancedCpuUsageSection(ColorScheme colorScheme) {
    if (_advancedCpuUsage == null) return const SizedBox.shrink();

    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.show_chart,
                  color: colorScheme.secondary,
                  size: 28,
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: Text(
                    'Advanced CPU Usage',
                    style: Theme.of(context).textTheme.titleLarge?.copyWith(
                          fontWeight: FontWeight.bold,
                        ),
                  ),
                ),
                if (_refreshTimer != null)
                  Container(
                    padding:
                        const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                    decoration: BoxDecoration(
                      color: Colors.green.withValues(alpha: 0.2),
                      borderRadius: BorderRadius.circular(4),
                    ),
                    child: const Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Icon(Icons.refresh, size: 14, color: Colors.green),
                        SizedBox(width: 4),
                        Text(
                          'Live',
                          style: TextStyle(
                            color: Colors.green,
                            fontSize: 11,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ],
                    ),
                  ),
              ],
            ),
            const Divider(height: 24),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [
                    colorScheme.secondaryContainer.withValues(alpha: 0.5),
                    colorScheme.secondaryContainer.withValues(alpha: 0.2),
                  ],
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                ),
                borderRadius: BorderRadius.circular(12),
              ),
              child: Column(
                children: [
                  Text(
                    _advancedCpuUsage!.usagePercentageString,
                    style: Theme.of(context).textTheme.displayMedium?.copyWith(
                          color: colorScheme.onSurface,
                          fontWeight: FontWeight.bold,
                        ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    _advancedCpuUsage!.usageLevel,
                    style: Theme.of(context).textTheme.titleMedium?.copyWith(
                          color: colorScheme.onSurface.withValues(alpha: 0.7),
                        ),
                  ),
                  const SizedBox(height: 16),
                  LinearProgressIndicator(
                    value: _advancedCpuUsage!.usage / 100,
                    minHeight: 8,
                    borderRadius: BorderRadius.circular(4),
                    backgroundColor:
                        colorScheme.onSurface.withValues(alpha: 0.1),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 16),
            _buildInfoRow(
              'User Time',
              '${_advancedCpuUsage!.userTime.toStringAsFixed(2)}s',
              Icons.person,
              colorScheme,
            ),
            _buildInfoRow(
              'System Time',
              '${_advancedCpuUsage!.systemTime.toStringAsFixed(2)}s',
              Icons.settings,
              colorScheme,
            ),
            _buildInfoRow(
              'Active Threads',
              '${_advancedCpuUsage!.activeThreadCount} / ${_advancedCpuUsage!.totalThreadCount}',
              Icons.account_tree,
              colorScheme,
            ),
            _buildInfoRow(
              'Core Count',
              '${_advancedCpuUsage!.coreCount}',
              Icons.grid_view,
              colorScheme,
            ),
            if (_advancedCpuUsage!.detailedCoreUsages.isNotEmpty) ...[
              const SizedBox(height: 16),
              Text(
                'Per-Core Usage',
                style: Theme.of(context).textTheme.titleMedium?.copyWith(
                      fontWeight: FontWeight.bold,
                    ),
              ),
              const SizedBox(height: 12),
              ..._advancedCpuUsage!.detailedCoreUsages.map((core) {
                return Padding(
                  padding: const EdgeInsets.only(bottom: 12.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Text(
                            'Core ${core.coreIndex}',
                            style: TextStyle(
                              fontWeight: FontWeight.w600,
                              color: colorScheme.onSurface,
                            ),
                          ),
                          Text(
                            core.usageString,
                            style: TextStyle(
                              fontWeight: FontWeight.bold,
                              color: colorScheme.primary,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 6),
                      LinearProgressIndicator(
                        value: core.usage / 100,
                        minHeight: 6,
                        borderRadius: BorderRadius.circular(3),
                        backgroundColor:
                            colorScheme.onSurface.withValues(alpha: 0.1),
                        color: _getCoreColor(core.usage, colorScheme),
                      ),
                    ],
                  ),
                );
              }),
            ],
            if (_advancedCpuUsage!.threadDetails
                .where((t) => t.isActive && t.cpuUsage > 0)
                .isNotEmpty) ...[
              const SizedBox(height: 16),
              Text(
                'Active Threads (${_advancedCpuUsage!.threadDetails.where((t) => t.isActive && t.cpuUsage > 0).length})',
                style: Theme.of(context).textTheme.titleMedium?.copyWith(
                      fontWeight: FontWeight.bold,
                    ),
              ),
              const SizedBox(height: 12),
              Container(
                constraints: const BoxConstraints(maxHeight: 300),
                child: ListView.builder(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemCount: _advancedCpuUsage!.threadDetails
                              .where((t) => t.isActive && t.cpuUsage > 0)
                              .length >
                          10
                      ? 10
                      : _advancedCpuUsage!.threadDetails
                          .where((t) => t.isActive && t.cpuUsage > 0)
                          .length,
                  itemBuilder: (context, index) {
                    final activeThreads = _advancedCpuUsage!.threadDetails
                        .where((t) => t.isActive && t.cpuUsage > 0)
                        .toList();
                    final thread = activeThreads[index];
                    return Container(
                      margin: const EdgeInsets.only(bottom: 8),
                      padding: const EdgeInsets.all(12),
                      decoration: BoxDecoration(
                        color: colorScheme.surfaceContainerHighest,
                        borderRadius: BorderRadius.circular(8),
                      ),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Row(
                            mainAxisAlignment: MainAxisAlignment.spaceBetween,
                            children: [
                              Expanded(
                                child: Text(
                                  thread.displayName,
                                  style: const TextStyle(
                                    fontWeight: FontWeight.w600,
                                    fontSize: 13,
                                  ),
                                  maxLines: 1,
                                  overflow: TextOverflow.ellipsis,
                                ),
                              ),
                              Text(
                                thread.cpuUsageString,
                                style: TextStyle(
                                  fontWeight: FontWeight.bold,
                                  color: colorScheme.primary,
                                  fontSize: 13,
                                ),
                              ),
                            ],
                          ),
                        ],
                      ),
                    );
                  },
                ),
              ),
              if (_advancedCpuUsage!.threadDetails
                      .where((t) => t.isActive && t.cpuUsage > 0)
                      .length >
                  10)
                Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: Text(
                    'Showing 10 of ${_advancedCpuUsage!.threadDetails.where((t) => t.isActive && t.cpuUsage > 0).length} active threads',
                    style: TextStyle(
                      fontSize: 12,
                      color: colorScheme.onSurface.withValues(alpha: 0.5),
                      fontStyle: FontStyle.italic,
                    ),
                  ),
                ),
            ],
            const SizedBox(height: 16),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(
                  Icons.access_time,
                  size: 14,
                  color: colorScheme.onSurface.withValues(alpha: 0.5),
                ),
                const SizedBox(width: 6),
                Text(
                  'Last updated: ${_formatTimestamp(_advancedCpuUsage!.timestamp)}',
                  style: TextStyle(
                    fontSize: 12,
                    color: colorScheme.onSurface.withValues(alpha: 0.5),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildInfoRow(
    String label,
    String value,
    IconData icon,
    ColorScheme colorScheme,
  ) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 12.0),
      child: Row(
        children: [
          Icon(
            icon,
            size: 20,
            color: colorScheme.onSurface.withValues(alpha: 0.6),
          ),
          const SizedBox(width: 12),
          Expanded(
            child: Text(
              label,
              style: TextStyle(
                color: colorScheme.onSurface.withValues(alpha: 0.7),
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
          const SizedBox(width: 12),
          Flexible(
            child: Text(
              value,
              textAlign: TextAlign.end,
              style: TextStyle(
                color: colorScheme.onSurface,
                fontWeight: FontWeight.w600,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Color _getCoreColor(double usage, ColorScheme colorScheme) {
    if (usage > 80) return Colors.red;
    if (usage > 50) return Colors.orange;
    if (usage > 25) return colorScheme.primary;
    return Colors.green;
  }

  String _formatTimestamp(double timestamp) {
    final date =
        DateTime.fromMillisecondsSinceEpoch((timestamp * 1000).toInt());
    return '${date.hour.toString().padLeft(2, '0')}:'
        '${date.minute.toString().padLeft(2, '0')}:'
        '${date.second.toString().padLeft(2, '0')}';
  }

  String _formatCoreCount(Map<String, int?> cores) {
    final physical = cores['physical'];
    final logical = cores['logical'];
    final total = cores['total'];
    if (physical != null && logical != null) {
      return '$physical Physical, $logical Logical';
    }
    return '${total ?? 0} Cores';
  }

  String? _formatBytes(int? bytes) {
    if (bytes == null) return null;
    if (bytes >= 1024 * 1024 * 1024) {
      return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
    } else if (bytes >= 1024 * 1024) {
      return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB';
    }
    return '$bytes B';
  }
}
0
likes
150
points
14
downloads

Publisher

unverified uploader

Weekly Downloads

Comprehensive iOS device monitoring plugin with CPU, GPU, thermal, uptime, and advanced CPU usage tracking.

Repository (GitHub)

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on ios_device_monitor

Packages that implement ios_device_monitor