鸿蒙版Flutter如何实现token从本地读取,不上传git

首先,我们需要创建一个配置文件来存储token,然后修改代码从该文件读取token。

以下是修改方案:

1.首先,创建一个配置服务类来管理API token:

import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'dart:convert';

class ConfigService {
  static const String _configFileName = 'app_config.json';
  static const String _defaultToken = ''; // 默认为空,需要用户配置

  // 获取配置文件路径
  static Future<File> get _configFile async {
    final directory = await getApplicationDocumentsDirectory();
    return File('${directory.path}/$_configFileName');
  }

  // 读取配置
  static Future<Map<String, dynamic>> getConfig() async {
    try {
      final file = await _configFile;
      
      // 检查文件是否存在
      if (!await file.exists()) {
        // 如果不存在,创建默认配置
        await file.writeAsString(json.encode({
          'api_token': _defaultToken,
        }));
      }
      
      // 读取配置
      final contents = await file.readAsString();
      return json.decode(contents) as Map<String, dynamic>;
    } catch (e) {
      print('读取配置文件出错: $e');
      // 返回默认配置
      return {'api_token': _defaultToken};
    }
  }

  // 保存配置
  static Future<void> saveConfig(Map<String, dynamic> config) async {
    try {
      final file = await _configFile;
      await file.writeAsString(json.encode(config));
    } catch (e) {
      print('保存配置文件出错: $e');
    }
  }

  // 获取API Token
  static Future<String> getApiToken() async {
    final config = await getConfig();
    return config['api_token'] as String? ?? _defaultToken;
  }

  // 保存API Token
  static Future<void> saveApiToken(String token) async {
    final config = await getConfig();
    config['api_token'] = token;
    await saveConfig(config);
  }
}

2.然后,修改ranking_info_page.dart文件,从配置服务获取token:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:uuid/uuid.dart';
import 'tracking_model.dart';
import 'models/tracking_history_model.dart';
import 'services/tracking_history_service.dart';
import 'services/config_service.dart'; // 导入配置服务
import 'pages/tracking_history_page.dart';
import 'pages/about_page.dart';

// ... 现有代码 ...

class _RankingInfoPageState extends State<RankingInfoPage> {
  // ... 现有代码 ...
  String? _apiToken; // 添加API Token变量

  @override
  void initState() {
    super.initState();
    _loadApiToken(); // 加载API Token
  }

  // 加载API Token
  Future<void> _loadApiToken() async {
    final token = await ConfigService.getApiToken();
    setState(() {
      _apiToken = token;
    });
    
    // 如果token为空,显示设置对话框
    if (token.isEmpty) {
      // 延迟显示对话框,确保界面已经构建完成
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _showTokenSettingDialog();
      });
    }
  }

  // 显示Token设置对话框
  Future<void> _showTokenSettingDialog() async {
    final TextEditingController tokenController = TextEditingController();
    tokenController.text = _apiToken ?? '';
    
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // 用户必须点击按钮才能关闭对话框
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('设置API Token'),
          content: SingleChildScrollView(
            child: Column(
              children: <Widget>[
                const Text('请输入ALAPI的Token,用于查询快递信息。\n可以从 https://alapi.cn 获取。'),
                const SizedBox(height: 16),
                TextField(
                  controller: tokenController,
                  decoration: const InputDecoration(
                    labelText: 'API Token',
                    border: OutlineInputBorder(),
                  ),
                ),
              ],
            ),
          ),
          actions: <Widget>[
            TextButton(
              child: const Text('保存'),
              onPressed: () async {
                final token = tokenController.text.trim();
                if (token.isNotEmpty) {
                  await ConfigService.saveApiToken(token);
                  setState(() {
                    _apiToken = token;
                  });
                  Navigator.of(context).pop();
                } else {
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Token不能为空')),
                  );
                }
              },
            ),
          ],
        );
      },
    );
  }

  Future<void> _queryTracking() async {
    // 检查Token是否已设置
    if (_apiToken == null || _apiToken!.isEmpty) {
      _showTokenSettingDialog();
      return;
    }

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

    // ... 现有代码 ...

    try {
      final response = await http.post(
        Uri.parse('https://v3.alapi.cn/api/tracking'),
        body: {
          'token': _apiToken, // 使用从配置中读取的token
          'number': number,
          'com': _selectedCompany,
          'phone': phone,
        },
      );

      // ... 现有代码 ...
    } catch (e) {
      // ... 现有代码 ...
    }
  }

  // ... 现有代码 ...

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // ... 现有代码 ...
      appBar: AppBar(
        // ... 现有代码 ...
        actions: [
          // 添加设置Token的按钮
          IconButton(
            icon: const Icon(Icons.vpn_key),
            tooltip: '设置API Token',
            onPressed: _showTokenSettingDialog,
          ),
          // ... 现有的按钮 ...
        ],
      ),
      // ... 现有代码 ...
    );
  }

  // ... 现有代码 ...
}

3.最后,需要在pubspec.yaml中添加path_provider依赖:

dependencies:
  flutter:
    sdk: flutter
  http: ^1.1.0
  uuid: ^4.0.0
  url_launcher: ^6.1.14
  flutter_phone_direct_caller: ^2.1.1
  path_provider: ^2.1.1  # 添加这一行
  # ... 其他依赖
  
dependency_overrides:
 shared_preferences:
    git:
      url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
      path: "packages/shared_preferences/shared_preferences"
 url_launcher:
    git:
      url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
      path: "packages/url_launcher/url_launcher"
 path_provider:
    git:
      url: "https://gitcode.com/openharmony-sig/flutter_packages.git"
      path: "packages/path_provider/path_provider"
 flutter_phone_direct_caller:
    git:
      url: "https://gitcode.com/openharmony-sig/fluttertpc_flutter_phone_direct_caller.git"

flutter:
  uses-material-design: true

这样修改后,API Token将从本地配置文件读取,而不是硬编码在代码中。用户首次使用应用时,会弹出对话框要求设置Token。用户也可以通过点击AppBar上的新增按钮随时修改Token。

这种方式可以确保敏感信息不会被上传到Git仓库中,提高了应用的安全性。

大家可以尝试啦。

效果如图:

image-20250309092601752


坚果
80 声望9 粉丝