Dart Flutter Test License

lib

Playstore

?Encrypto:轻松的文件加密

介绍?

想安全地加密您的私人和机密文件吗?

使用Encrypto,您可以轻松安全地保护所有重要文件,界面有趣且易于使用。

演示 ?

demo.mp4

主要特点 ?

✔支持所有文件类型(PDF、MP3、MP4、PNG、DOCX等) ✔从应用外部添加文件 ✔从应用内分享转换后的文件

算法 ?

所有内容均使用强大的加密算法进行加密:AES配合PKCS7填充

用法 ?

要克隆并运行此应用程序,您需要在计算机上安装gitflutter。在命令行中

# Clone this repository
$ git clone https://github.com/Shadow60539/encrypto_app.git

# Go into the repository
$ cd encrypto_app

# Install dependencies
$ flutter packages get

# Run the app
$ flutter run

软件包 ?

描述
file_cryptor FileCryptor用于加密和解密文件。
文件选择器 允许您使用原生文件浏览器选择单个或多个文件,并支持扩展名过滤的软件包。
mockito 受Mockito启发的模拟框架,提供用于模拟、桩、行为验证和存根的API。
open_file 一个插件,可以调用原生APP来打开文件,并在flutter中返回字符串结果。
path_provider 一个用于查找文件系统上常用位置的Flutter插件
permission_handler 此插件提供了一个跨平台(iOS、Android)API来请求权限和检查其状态。
lottie Lottie是Android和iOS的移动库,可以解析Adobe After Effects导出的json动画(通过Bodymovin),并在移动设备上本地渲染。
share_plus 一个Flutter插件,可以通过平台的共享对话框共享内容。
flutter_archive 创建和提取ZIP存档文件。
flutter_bloc 状态管理。
freezed 为具有简单语法/API且不牺牲功能的不可变类生成代码。
dartz Dart中的函数式编程。
injectable Injectable是get_it的一个方便的代码生成器。
fancy_text_reveal ?‍♂️ 我的软件包。一种炫酷的显示小部件的方式。
animated_text_kit 一个Flutter软件包项目,其中包含一系列酷炫漂亮的文本动画。
flutter_svg Flutter的SVG渲染和小部件库。
package_info_plus Flutter 插件,用于查询应用程序包信息,例如 iOS 上的 CFBundleVersion 或 Android 上的 versionCode。
flutter_isolate FlutterIsolate提供了一种在Flutter中启动Dart Isolate的方法,该方法可以与Flutter插件一起使用。
change_app_package_name 用一个命令更改应用包名。
firebase_core Flutter的Firebase Core插件,支持连接到多个Firebase应用。
cloud_firestore Flutter的Cloud Firestore插件,一个云托管的NoSQL数据库,支持Android和iOS的实时同步和离线功能。
equatable 一个Dart软件包,可帮助实现基于值的相等性,而无需显式重写==和hashCode。
countup 一个Flutter插件,可以帮助您构建动画计数器文本。
flutter_keyboard_visibility Flutter插件,用于检测Android和iOS上软键盘的可见状态
flutter_launcher_icons 一个简化更新Flutter应用启动器图标任务的软件包。
flutter_native_splash 使用背景颜色和启动图像自定义Flutter的默认白色原生启动屏幕。
fake_cloud_firestore Cloud Firestore的模拟实现
in_app_update 使用官方Android API在Android上启用应用内更新。
restart_app 一个简单的软件包,可以帮助您通过单个函数调用来重新启动整个Android应用。
flutter_lints 此软件包包含一套推荐的Flutter应用、软件包和插件的lint规则,以鼓励良好的编码实践。
receive_sharing_intent 一个Flutter插件,允许Flutter应用从其他应用接收共享的照片、视频、文本、URL或任何其他文件类型。

目录结构 ?

lib 目录结构如下

├── application
|    ├── crypto
|    |    ├── crypto_bloc.dart
|    |    ├── crypto_event.dart
|    |    ├── crypto_state.dart
|    |── save
|    |    ├── save_bloc.dart
|    |    ├── save_event.dart
|    |    ├── save_state.dart
├── core
|    |── enums.dart
|    |── extension.dart
|    |── navigation_service.dart
|    |── usecase.dart
├── domain
|    |── entity
|    |    ├── file_count.dart
|    |── failure
|    |    ├── crypto_failure.dart
|    |    ├── save_failure.dart
|    |── repoitory
|    |    ├── i_crypto_repo.dart
|    |    ├── i_save_repo.dart
|    |── usecase
|    |    ├── decrypt_file.dart
|    |    ├── encrypt_file.dart
|    |    ├── get_file_count.dart
|    |    ├── increment_file_count.dart
|    |    ├── save_file.dart
|    |    ├── share_file.dart
├── infrastructure
|    |── core
|    |    ├── firebase_helper.dart    
|    |    ├── injection_module.dart    
|    |    ├── permission_handler.dart    
|    |── data
|    |    ├── crypto_data_source.dart
|    |    ├── save_data_source.dart
|    |── exception
|    |    ├── crypto_exception.dart
|    |    ├── save_exception.dart
|    |── model
|    |    ├── file_count_model.dart
|    |── repository
|    |    ├── crypto_repo.dart
|    |    ├── save_repo.dart
├── presentation
|    |── core
|    |    ├── palette.dart
|    |── pages
|    |    ├── home_page.dart
|    |    ├── result_page.dart
|    |    ├── splash_page.dart
|    |── widgets
|    |    ├── add_file_widget.dart
|    |    ├── app_version_widget.dart
|    |    ├── app_widget.dart
|    |    ├── count_animated_widget.dart
|    |    ├── key_widget.dart
|    |    ├── moon_animated_widget.dart
|    |    ├── permission_dialog.dart
|    |    ├── title_animated_widget.dart
|    |    ├── usecase_button.dart
├── injection.dart
├── main.dart

应用内购买 v3.0.5

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_encrypto/application/ad/ad_bloc.dart';
import 'package:flutter_encrypto/core/navigation_service.dart';
import 'package:in_app_purchase/in_app_purchase.dart';

const String kRemoveAds = "remove_ads";

class PurchaseProvider with ChangeNotifier {
  bool _isAvailable = false;
  final InAppPurchase _iap = InAppPurchase.instance;
  List<ProductDetails> _products = [];
  List<PurchaseDetails> _purchases = [];
  late StreamSubscription _subscription;
  InAppPurchase get iap => _iap;
  bool get isAvailable => _isAvailable;

  Future<void> initialize() async {
    _isAvailable = await _iap.isAvailable();
    _subscription = _iap.purchaseStream.listen(_listener);
    _getProducts();
    _getPastPurchases();
  }

  void _listener(List<PurchaseDetails> purchaseDetails) {
    if (purchaseDetails.isEmpty) {
      return;
    }

    _verifyPurchase(purchaseDetails[0]);
    _purchases.addAll(purchaseDetails);
    notifyListeners();
  }

  Future<void> _verifyPurchase(PurchaseDetails purchaseDetail) async {
    final bool isRemoveAdsPurchase = purchaseDetail.productID == kRemoveAds;

    if (!isRemoveAdsPurchase) {
      return;
    }

    final bool isPurchasePending = purchaseDetail.pendingCompletePurchase;

    if (isPurchasePending) {
      await _iap.completePurchase(purchaseDetail);
    }

    final bool isPurchaseSuccess =
        purchaseDetail.status == PurchaseStatus.purchased ||
            purchaseDetail.status == PurchaseStatus.restored;

    if (!isPurchaseSuccess) {
      return;
    }

    // Remove ads
    BlocProvider.of<AdBloc>(globalContext, listen: false)
        .add(AdEvent.removeAds());
  }

  void cancelSubscription() {
    _subscription.cancel();
  }

  Future<void> _getPastPurchases() async {
    await _iap.restorePurchases();
  }

  Future<void> _getProducts() async {
    final ProductDetailsResponse response =
        await _iap.queryProductDetails({kRemoveAds});

    _products = response.productDetails;
    notifyListeners();
  }

  Future<void> buyRemoveAds() async {
    final PurchaseParam _removeAdParam =
        PurchaseParam(productDetails: _products[0]);
    await _iap.buyNonConsumable(purchaseParam: _removeAdParam);
  }
}

应用内更新 v3.0.0

  Future<void> _checkForUpdate() async {
    final AppUpdateInfo info = await InAppUpdate.checkForUpdate();
    final bool isUpdateAvailable =
        info.updateAvailability == UpdateAvailability.updateAvailable;
    if (isUpdateAvailable) {
      final result = await InAppUpdate.performImmediateUpdate();
      if (result == AppUpdateResult.userDeniedUpdate ||
          result == AppUpdateResult.inAppUpdateFailed) {
        // close the app
        SystemNavigator.pop();
      }

      if (result == AppUpdateResult.success) {
        Restart.restartApp();
      }
    }
  }

Google移动广告 v1.2.0

在 main.dart 中

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Include
  MobileAds.instance.initialize();
  // runApp(const MyApp());
}

声明 bannerAd, isBannerAdLoaded, interstitialAd 在状态中

  late BannerAd bannerAd;
  bool isBannerAdLoaded = false;
  InterstitialAd? interstitialAd;

  @override
  void initState() {
    _createInterstitialAd();
    _createBannerAd();
    super.initState();
  }

  @override
  void dispose() {
    bannerAd.dispose();
    interstitialAd?.dispose();
    super.dispose();
  }

插页广告设置

  Future<void> _createInterstitialAd({int counter=0}) async {
    if (counter > 3) return;
    await InterstitialAd.load(
      adUnitId: "ca-app-pub-3940256099942544/8691691433",
      request: const AdRequest(),
      adLoadCallback: InterstitialAdLoadCallback(
        onAdLoaded: (ad) {
          interstitialAd = ad;
          setState(() {});
        },
        onAdFailedToLoad: (ad) {
          interstitialAd = null;
          _createInterstitialAd( counter: counter + 1);
          setState(() {});
        },
      ),
    );
  }

    Future<void> _showInterstitialAd() async {
    if (interstitialAd == null) return;
    interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
      onAdDismissedFullScreenContent: (ad) {
        ad.dispose();
        _createInterstitialAd();
      },
      onAdFailedToShowFullScreenContent: (ad, _) {
        ad.dispose();
        _createInterstitialAd();
      },
    );
    await interstitialAd!.show();
  }

横幅广告设置

Future<void> _createBannerAd() async {
    bannerAd = BannerAd(
      size: AdSize.banner,
      adUnitId: "ca-app-pub-3940256099942544/6300978111",
      listener: BannerAdListener(
        onAdLoaded: (_) {
          setState(() {
            isBannerAdLoaded = true;
          });
        },
        onAdFailedToLoad: (ad, _) {
          ad.dispose();
        },
      ),
      request: const AdRequest(),
    );

    await bannerAd.load();
  }

GitHub

查看 Github