device_doctor 1.0.0 copy "device_doctor: ^1.0.0" to clipboard
device_doctor: ^1.0.0 copied to clipboard

跨平台设备环境检测:模拟器/虚拟机、代理/VPN、Root/越狱、签名与设备信息。Android 深度检测 + iOS/Windows/macOS/Linux/Web Dart 回退。

example/lib/main.dart

import 'dart:convert';

import 'package:device_doctor/device_doctor.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

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

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

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

class _MyAppState extends State<MyApp> {
  static const doctor = DeviceDoctor();
  String _output = '点击下方按钮开始全量检测';
  bool _loading = false;

  Future<void> _runChecks() async {
    setState(() {
      _loading = true;
      _output = '检测中…';
    });

    // 电话权限仅 Android 有意义;桌面/Web 上 permission_handler 会抛
    // MissingPluginException,捕获后继续检测。
    try {
      final status = await Permission.phone.request();
      debugPrint('permission phone: $status');
    } catch (_) {
      debugPrint('permission phone not available on this platform');
    }

    try {
      final buf = StringBuffer();

      buf.writeln('platformVersion: ${await doctor.platformVersion}');
      buf.writeln('apiLevel: ${await doctor.apiLevel}');
      buf.writeln('deviceModel: ${await doctor.deviceModel}');
      buf.writeln('deviceManufacturer: ${await doctor.deviceManufacturer}');
      buf.writeln('deviceName: ${await doctor.deviceName}');
      buf.writeln('productName: ${await doctor.productName}');
      buf.writeln('cpuName: ${await doctor.cpuName}');
      buf.writeln('hardware: ${await doctor.hardware}');

      final imei = await doctor.deviceIMEINumber;
      buf.writeln('deviceIMEINumber: ${imei ?? "(不可用,Android 10+ 受限)"}');

      for (final t in ['SHA-1', 'SHA-256', 'MD5']) {
        final sigs = await doctor.getSignatures(t);
        buf.writeln('signatures($t): ${sigs.isEmpty ? "(无)" : jsonEncode(sigs)}');
      }

      final simInfo = await doctor.getSimulatorInfo();
      buf.writeln('getSimulatorInfo: ${simInfo.isEmpty ? "(无命中)" : jsonEncode(simInfo)}');
      final simRaw = await doctor.isSimulator();
      buf.writeln('isSimulator raw: ${jsonEncode(simRaw)}');
      buf.writeln('isEmulator(threshold=5): ${await doctor.isEmulator()}');
      buf.writeln('isEmulator(threshold=8): ${await doctor.isEmulator(threshold: 8)}');

      buf.writeln('isProxy: ${await doctor.isProxy()}');
      buf.writeln('isOpenVPN: ${await doctor.isOpenVPN()}');
      buf.writeln('isRootEnv: ${await doctor.isRootEnv()}');

      final out = buf.toString();
      debugPrint(out);
      if (!mounted) return;
      setState(() => _output = out);
    } catch (e, st) {
      debugPrint('checks failed: $e\n$st');
      if (!mounted) return;
      setState(() => _output = '检测失败: $e');
    } finally {
      if (mounted) setState(() => _loading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('device_doctor 示例')),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              _ActionButton(
                label: _loading ? '检测中…' : '一键检测全部环境项',
                onTap: _loading ? null : _runChecks,
              ),
              Row(
                children: [
                  Expanded(
                    child: _ActionButton(
                      label: '清空缓存',
                      onTap: _loading
                          ? null
                          : () async {
                              final messenger = ScaffoldMessenger.of(context);
                              await doctor.clearSimulatorCache();
                              if (!mounted) return;
                              messenger.showSnackBar(
                                const SnackBar(content: Text('已清空模拟器/包名/CPU 缓存')),
                              );
                            },
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: _ActionButton(
                      label: '添加自定义指纹',
                      onTap: _loading
                          ? null
                          : () async {
                              final messenger = ScaffoldMessenger.of(context);
                              await doctor.addCustomEmulatorPackages(['com.example.myemu']);
                              if (!mounted) return;
                              messenger.showSnackBar(
                                const SnackBar(content: Text('已添加 com.example.myemu')),
                              );
                            },
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 16),
              SelectableText(
                _output,
                style: const TextStyle(fontSize: 12, fontFamily: 'monospace'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class _ActionButton extends StatelessWidget {
  const _ActionButton({required this.label, required this.onTap});
  final String label;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 12),
      child: ElevatedButton(
        onPressed: onTap,
        child: Text(label),
      ),
    );
  }
}
0
likes
130
points
289
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

跨平台设备环境检测:模拟器/虚拟机、代理/VPN、Root/越狱、签名与设备信息。Android 深度检测 + iOS/Windows/macOS/Linux/Web Dart 回退。

Repository (GitHub)
View/report issues

Topics

#device #emulator #vpn #proxy #root

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on device_doctor

Packages that implement device_doctor