Skip to content

Commit

Permalink
应用内升级检测逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
toly1994328 committed Jul 20, 2021
1 parent d45d1e4 commit 1f0ff23
Show file tree
Hide file tree
Showing 15 changed files with 669 additions and 14 deletions.
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

<application
android:name="io.flutter.app.FlutterApplication"
Expand Down
40 changes: 40 additions & 0 deletions lib/app/api/app_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'package:flutter_unit/app/res/path_unit.dart';
import 'package:flutter_unit/app/utils/http_utils/http_util.dart';
import 'package:flutter_unit/app/utils/http_utils/result_bean.dart';

class AppInfoApi {

static Future<ResultBean<AppInfo>> getAppVersion() async {
String errorMsg = "";
var result = await HttpUtil.getInstance()
.client
.get(PathUnit.appInfo)
.catchError((err) {
errorMsg = err.toString();
});

// 获取的数据非空且 status = true
if (result.data != null && result.data['status']) {
// 说明有数据
if (result.data['data'] != null) {
return ResultBean.ok<AppInfo>(
AppInfo(
appName: result.data['data']['appName'],
appVersion: result.data['data']['appVersion'],
appUrl: result.data['data']['appUrl'],
));
} else {
return ResultBean.ok<AppInfo>(null);
}
}
return ResultBean.error('请求错误: $errorMsg');
}
}

class AppInfo{
final String appName;
final String appVersion;
final String appUrl;

AppInfo({this.appName, this.appVersion, this.appUrl});
}
1 change: 1 addition & 0 deletions lib/app/res/path_unit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class PathUnit{

static const categoryDataSync = '/categoryData/sync';
static const categoryData = '/categoryData';
static const appInfo = '/appInfo/name/FlutterUnit';

static const login = '/login';

Expand Down
16 changes: 16 additions & 0 deletions lib/app/utils/Toast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,20 @@ class Toast {
backgroundColor: color??Theme.of(context).primaryColor,
));
}

static void error(BuildContext context,String msg){
toast(context,msg, color:Colors.red, );
}

static void warning(BuildContext context,String msg){
toast(context,msg, color:Colors.orange, );
}

static void success(BuildContext context,String msg){
toast(context,msg, color:Theme.of(context).primaryColor, );
}

static void green(BuildContext context,String msg){
toast(context,msg, color:Colors.green, );
}
}
14 changes: 14 additions & 0 deletions lib/app/utils/convert.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,18 @@ class Convert {
GalleryType.anim: "动画手势",
GalleryType.art: "艺术画廊",
};

static String convertFileSize(int size){
if(size==null) return '0 kb';
double result = size / 1024.0;
if(result<1024){
return "${result.toStringAsFixed(2)}Kb";
}else if(result>1024&&result<1024*1024){
return "${(result/1024).toStringAsFixed(2)}Mb";
}else{
return "${(result/1024/1024).toStringAsFixed(2)}Gb";
}
}


}
197 changes: 197 additions & 0 deletions lib/painter_system/particle/out/clock_fx.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import 'dart:math';

import 'package:flutter/material.dart';
import 'rnd.dart';

import 'particle.dart';


final easingDelayDuration = Duration(seconds: 10);

/// Probabilities of Hour, Minute, Noise.
// final particleDistributions = [2, 4, 100];

/// Number of "arms" to emit noise particles from center.
final int noiseAngles = 2000;

/// Threshold for particles to go rouge. Lower = more particles.
final rougeDistributionLmt = 85;

/// Threshold for particles to go jelly. Lower = more particles.
final jellyDistributionLmt = 97;


class ClockFx with ChangeNotifier {

double width; //宽
double height;//高
double sizeMin; // 宽高最小值
Offset center; //画布中心
Rect spawnArea; // 粒子活动区域

List<Particle> particles; // 所有粒子

int numParticles;// 最大粒子数

DateTime time; //时间

ClockFx({
@required Size size,
@required DateTime time,
this.numParticles = 5000,
}) {
this.time = time;
particles = List<Particle>.filled(numParticles, null);
setSize(size);
}

void init() {
for (int i = 0; i < numParticles; i++) {
particles[i] = Particle(color:Colors.black );
resetParticle(i);
}
}

void setTime(DateTime time) {
this.time = time;
}

void setSize(Size size) {
width = size.width;
height = size.height;
sizeMin = min(width, height);
center = Offset(width / 2, height / 2);
spawnArea = Rect.fromLTRB(
center.dx - sizeMin / 100,
center.dy - sizeMin / 100,
center.dx + sizeMin / 100,
center.dy + sizeMin / 100,
);
init();
}

/// Resets a particle's values.
Particle resetParticle(int i) {
Particle p = particles[i];
p.size = p.a = p.vx = p.vy = p.life = p.lifeLeft = 0;
p.x = center.dx;
p.y = center.dy;
return p;
}

void tick(Duration duration) {
updateParticles(duration); // 更新粒子
notifyListeners();// 通知监听者(画板)更新
}

void updateParticles(Duration duration){
var secFrac = DateTime.now().millisecond / 1000;

var vecSpeed = duration.compareTo(easingDelayDuration) > 0
? max(.2, Curves.easeInOutSine.transform(1 - secFrac))
: 1;

var vecSpeedInv = Curves.easeInSine.transform(secFrac);

var maxSpawnPerTick = 10;

particles.asMap().forEach((i, p) {
p.x -= p.vx * vecSpeed;
p.y -= p.vy * vecSpeed;

p.dist = _getDistanceFromCenter(p);
p.distFrac = p.dist / (sizeMin / 2);

p.lifeLeft = p.life - p.distFrac;

p.vx -= p.lifeLeft * p.vx * .001;
p.vy -= p.lifeLeft * p.vy * .001;

if (p.lifeLeft < .3) {
p.size -= p.size * .0015;
}

if (p.distribution > rougeDistributionLmt && p.distribution < jellyDistributionLmt) {
var r = Rnd.getDouble(.2, 2.5) * vecSpeedInv * p.distFrac;
p.x -= p.vx * r + (p.distFrac * Rnd.getDouble(-.4, .4));
p.y -= p.vy * r + (p.distFrac * Rnd.getDouble(-.4, .4));
}

if (p.distribution >= jellyDistributionLmt) {
var r = Rnd.getDouble(.1, .9) * vecSpeedInv * (1 - p.lifeLeft);
p.x += p.vx * r;
p.y += p.vy * r;
}

if (p.lifeLeft <= 0 || p.size <= .5) {
resetParticle(i);
if (maxSpawnPerTick > 0) {
_activateParticle(p);
maxSpawnPerTick--;
}
}

});
}

void _activateParticle(Particle p) {
p.x = Rnd.getDouble(spawnArea.left, spawnArea.right);
p.y = Rnd.getDouble(spawnArea.top, spawnArea.bottom);
p.isFilled = Rnd.getBool();
p.size = Rnd.getDouble(3, 8);
p.distFrac = 0;
p.distribution = Rnd.getInt(1, 2);

double angle = Rnd.ratio * pi * 2;


var am = _getMinuteRadians();
var ah = _getHourRadians() % (pi * 2);
var d = pi / 18;
//
// Probably not the most efficient solution right here.
do {
angle = Rnd.ratio * pi * 2;
} while (_isBetween(angle, am - d, am + d) ||
_isBetween(angle, ah - d, ah + d) );

p.life = Rnd.getDouble(0.75, .8);

p.size = sizeMin *
(Rnd.ratio > .8
? Rnd.getDouble(.0015, .003)
: Rnd.getDouble(.002, .006));

p.vx = sin(-angle);
p.vy = cos(-angle);

p.a = atan2(p.vy, p.vx) + pi;

double v = Rnd.getDouble(.5, 1);

p.vx *= v;
p.vy *= v;
}

double _getDistanceFromCenter(Particle p) {
var a = pow(center.dx - p.x, 2);
var b = pow(center.dy - p.y, 2);
return sqrt(a + b);
}

/// Gets the radians of the hour hand.
double _getHourRadians() =>
(time.hour * pi / 6) +
(time.minute * pi / (6 * 60)) +
(time.second * pi / (360 * 60));

/// Gets the radians of the minute hand.
double _getMinuteRadians() =>
(time.minute * (2 * pi) / 60) + (time.second * pi / (30 * 60));

/// Checks if a value is between two other values.
bool _isBetween(double value, double min, double max) {
return value >= min && value <= max;
}

}
88 changes: 88 additions & 0 deletions lib/painter_system/particle/out/clock_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import 'dart:math';
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

import 'clock_fx.dart';

/// create by 张风捷特烈 on 2021/2/7
/// contact me by email 1981462002@qq.com
/// 说明:
class ClockWidget extends StatefulWidget {
final double radius;

const ClockWidget({Key key, this.radius = 100}) : super(key: key);

@override
_ClockWidgetState createState() => _ClockWidgetState();
}

class _ClockWidgetState extends State<ClockWidget>
with SingleTickerProviderStateMixin {
Ticker _ticker;
ClockFx _fx;

@override
void initState() {
super.initState();
_ticker = createTicker(_tick)..start();
_fx = ClockFx(
size: Size(widget.radius * 2, widget.radius * 2),
time: DateTime.now(),
);
}

@override
void dispose() {
_ticker.dispose();
_fx.dispose();
super.dispose();
}

void _tick(Duration duration) {
_fx.tick(duration);
if (_fx.time.second != DateTime.now().second) {
_fx.setTime(DateTime.now());
}
}

@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(widget.radius * 2, widget.radius * 2),
painter: ClockFxPainter(fx: _fx),
);
}
}

/// Alpha value for noise particles.
const double noiseAlpha = 160;

class ClockFxPainter extends CustomPainter {
final ClockFx fx;

ClockFxPainter({@required this.fx}) : super(repaint: fx);

@override
void paint(Canvas canvas, Size size) {
fx.particles.forEach((p) {
double a;
a = max(0.0, (p.distFrac - .13) / p.distFrac) * 255;
a = min(a, min(noiseAlpha, p.lifeLeft * 3 * 255));
int alpha = a.floor();

Paint circlePaint = Paint()
..style = PaintingStyle.fill
..color = p.color.withAlpha(alpha);

canvas.drawCircle(Offset(p.x, p.y), p.size, circlePaint);
});
}

@override
bool shouldRepaint(covariant ClockFxPainter oldDelegate) =>
oldDelegate.fx != fx;
}
Loading

0 comments on commit 1f0ff23

Please sign in to comment.