?Encrypto:轻松的文件加密
介绍?
想安全地加密您的私人和机密文件吗?
使用Encrypto,您可以轻松安全地保护所有重要文件,界面有趣且易于使用。
演示 ?
demo.mp4
主要特点 ?
✔支持所有文件类型(PDF、MP3、MP4、PNG、DOCX等) ✔从应用外部添加文件 ✔从应用内分享转换后的文件
算法 ?
所有内容均使用强大的加密算法进行加密:AES配合PKCS7填充
用法 ?
要克隆并运行此应用程序,您需要在计算机上安装git和flutter。在命令行中
# 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();
}

