声明:这是学flutter的第一个应用,垃圾堆中的代码,

然后,大神请无视,如果作为flutter初学者,可以尝试看看

dependencies:flutter:sdk: flutterdio: ^3.0.9video_player: ^0.10.11+1http: ^0.12.1getflutter: ^1.0.11permission_handler: ^4.2.0fluttertoast: ^4.0.1path_provider: ^1.1.0

引入依赖

import 'dart:convert' as convert;
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:dio/dio.dart';
import 'douyin.dart';
import 'httpHeaders.dart';
import 'package:permission_handler/permission_handler.dart';
import 'oplayer.dart';
import 'package:fluttertoast/fluttertoast.dart';
void main() {runApp(MaterialApp(debugShowCheckedModeBanner: false, home: HomePage()));
}//不显示debug
class HomePage extends StatefulWidget {_HomePageState createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {String showText = '请输入网址';String vurl = '';bool hil = false;var _username = new TextEditingController();@overrideWidget build(BuildContext context) {var inputDecoration = InputDecoration(icon: Icon(Icons.mode_edit),hintText: "https://",);return Scaffold(appBar: AppBar(title: Text('抖音解析无水印'),),body: Container(alignment: Alignment.center,child: SingleChildScrollView(child: Column(children: <Widget>[Container(alignment: Alignment.center,child: Image.asset('asstes/52377818.png',fit: BoxFit.fill,width: 300,height: 400,)),TextField(decoration: inputDecoration,controller: _username,),RaisedButton(onPressed: () {_juejin(url: this._username.text);hil = true;},child: Text('解析1'),),RaisedButton(onPressed: () {pppo(this._username.text).then((val) {setState(() {if (val == 5) {showText = '解析失败!!!';vurl = '';} else {vurl = val['url'];//print(vurl);
//https://v.douyin.com/JJVsUkT//http://v.douyin.com/xGSE7PshowText = '解析完成';}});});hil = true;},child: Text('解析2'),),Text(showText),//vvcc(),//Text(showText),],),),));}vvcc() {if (showText == '请输入网址') {return Center();} else if (showText == '解析失败!!!') {return Text('1.网络信号差.\n2.输入有误\n3.解析失效');} else {if (vurl != '') {return IconButton(onPressed: () {//   Navigator.push(//       context, MaterialPageRoute(builder: (context) => DYixz(vurl)));// },Navigator.of(context).push(MaterialPageRoute(builder: (context)=>DYixz(vurl)));},icon: Icon(Icons.file_download, size: 46, color: Colors.red),);}else{return Center(child: CircularProgressIndicator(strokeWidth: 2.0),);}}}pppo(d) async {d = 'http://tool.bbkl.top/dyjx/ajax.php?act=dy&url=$d';try {var response = await http.get(d);if (response.statusCode == 200) {var jsonResponse = convert.jsonDecode(response.body);return jsonResponse;} else {return 5;}} catch (e) {print(e);return e;}}void _juejin({String url}) {//print('开始向极客时间请求数据..................');url = 'https://www.ppwit.com/dy/dy.php?url=$url';getVideos(url).then((val) {setState(() {String bbb = '&ratio=720p&line=0';if (val == 5) {showText = '解析失败!!!';vurl = '';} else {var pp = val.itemList[0].video.playaddr.uri;vurl = 'https://aweme.snssdk.com/aweme/v1/play/?video_id=$pp$bbb';//http://v.douyin.com/xGSE7PshowText = '解析完成';}});});}getVideos(v) async {try {var response = await http.get(v);if (response.statusCode == 200) {var jsonResponse = convert.jsonDecode(response.body);VideoData videoData = VideoData.fromJson(jsonResponse);if (videoData.statusCode == 5) {return videoData.statusCode;} else {return videoData;}}} catch (e) {return print(e);}}Future getHttp(url) async {try {Response response;Dio dio = new Dio();dio.options.headers = httpHeaders85;response = await dio.get(url);//print(response.toString());return response.data;} catch (e) {return print(e);}}
}//自定义组件
class DYixz extends StatefulWidget {final vurl;final dpz;DYixz(this.vurl, {this.dpz});@override_DYixzState createState() => _DYixzState();
}class _DYixzState extends State<DYixz> with SingleTickerProviderStateMixin {AnimationController controller;Animation<double> animation;Random numl = Random();List numo = [];var dpz;Color _colord;void initState() {_colord = Colors.white;numo.add(numl.nextInt(3000));numo.add(numl.nextInt(numo[0]));numo.add(numl.nextInt(numo[0]));dpz = widget.dpz ?? numo;super.initState();controller = AnimationController(duration: const Duration(milliseconds: 1200), vsync: this);//Curvedanimation弹性动画.非线性的animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn)..addStatusListener((status) {if (status == AnimationStatus.completed) {//动画在结束时停止的状态controller.reverse(); //颠倒} else if (status == AnimationStatus.dismissed) {//动画在开始时就停止的状态//controller.forward(); //向前}})..addListener(() {setState(() {});});}@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(body: Stack(children: <Widget>[Container(child: Oplayer(url: widget.vurl)),ScaleTransition(alignment: Alignment.center,scale: animation,child: Align(//alignment: Alignment.center,widthFactor: 100,heightFactor: 100,child: Icon(Icons.favorite, size: 200, color: Colors.red[400])),),Positioned(bottom: 20,right: 0,child: Container(margin: EdgeInsets.fromLTRB(0, 0, 15, 120),child: Column(children: <Widget>[Container(child: Column(children: <Widget>[IconButton(onPressed: () {setState(() {if (_colord == Colors.white) {_colord = Colors.red;//红心+1controller.forward();} else {_colord = Colors.white;}});},icon: Icon(Icons.favorite, size: 36, color: _colord),),Text('点一下',style: TextStyle(fontSize: 15,color: Colors.white,decoration: TextDecoration.none),)])),SizedBox(height: 10),Container(child: Column(children: <Widget>[IconButton(onPressed: () {//downloading(widget.vurl);Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>Pdownloading(widget.vurl)));},icon: Icon(Icons.file_download, size: 36, color: _colord),),Text('down',style: TextStyle(fontSize: 15,color: Colors.white,decoration: TextDecoration.none),),]),),SizedBox(height: 10),Container(child: Column(children: <Widget>[IconButton(onPressed: () {Navigator.push(context,MaterialPageRoute(builder: (context) => HomePage()));},icon: Icon(Icons.near_me, size: 36, color: _colord),),Text('返回',style: TextStyle(fontSize: 15,color: Colors.white,decoration: TextDecoration.none),),])),])))]));}
}class Pdownloading extends StatefulWidget {final cvv;Pdownloading(this.cvv);@override_PdownloadingState createState() => _PdownloadingState();
}class _PdownloadingState extends State<Pdownloading> {Random numl = Random();double currentProgress = 0.0;///下载文件的网络路径var nu;String vvvd;@overridevoid initState() {super.initState();nu = numl.nextInt(300000000)..toString();applyPermission();}//_requestPermissions();@overridevoid dispose() {super.dispose();}@overrideWidget build(BuildContext context) {return Center(child: Scaffold(body: Container(alignment: Alignment.center,child: (currentProgress == 0.0)? Container(child:Column(mainAxisSize: MainAxisSize.min, children: [Text('正在初始化...'),RaisedButton(onPressed: () {Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=>HomePage()));},child: Text('取消'),),Text('如果下载不成功,\n1请检查网络状态\2软件权限不足,\n请打开手机设置中的应用管理,\n权限管理,\n允许软件读写权限\n然后重启本软件,即可下载保存\n视频默认保存路径在Download中')])): Container(child:Column(mainAxisSize: MainAxisSize.min, children: [Text('正在下载'),Text(vvvd),RaisedButton(onPressed: () {Navigator.pushAndRemoveUntil(context,MaterialPageRoute(builder: (BuildContext context) {return HomePage();}), (route) => false);},child: Text('完成'),),Text('如果下载不成功,\n1请检查网络状态\2软件权限不足,\n请打开手机设置中的应用管理,\n权限管理,\n允许软件读写权限\n然后重启本软件,即可下载保存\n视频默认保存路径在Download中')])))));}//动态申请权限
Future applyPermission({String atcUrl, String atcName, BuildContext context}) async {
//    只有当用户同时点选了拒绝开启权限和不再提醒后才会truebool isSHow = await PermissionHandler().shouldShowRequestPermissionRationale(PermissionGroup.storage);// 申请结果  权限检测PermissionStatus permission = await PermissionHandler().checkPermissionStatus(PermissionGroup.storage);if (permission != PermissionStatus.granted) {//权限没允许//如果弹框不在出现了,那就跳转到设置页。//如果弹框还能出现,那就不用管了,申请权限就行了if (!isSHow) {await PermissionHandler().openAppSettings();} else {await PermissionHandler().requestPermissions([PermissionGroup.storage]);//此时要在检测一遍,如果允许了就下载。//没允许就就提示。PermissionStatus pp = await PermissionHandler().checkPermissionStatus(PermissionGroup.storage);if (pp == PermissionStatus.granted) {//去下载吧downApkFunction();} else {// 参数1:提示消息// 参数2:提示消息多久后自动隐藏// 参数3:位置Fluttertoast.showToast(msg: "请允许存储权限,并重试!",toastLength: Toast.LENGTH_SHORT,webBgColor: "#e74c3c",timeInSecForIosWeb: 5,);}}} else {//权限允许了,那就下载吧、downApkFunction();}}///使用dio 下载文件void downApkFunction() async {/// 申请写文件权限///创建DIODio dio = new Dio();//设置连接超时时间dio.options.connectTimeout = 500000;//设置数据接收超时时间dio.options.receiveTimeout = 500000;///参数一 文件的网络URL///参数二 下载的本地目录文件///参数三 下载监听try{ Response response = await dio.download(widget.cvv, "/storage/emulated/0/Download/$nu.mp4",onReceiveProgress: (received, total) {if (total != -1) {///当前下载的百分比例setState(() {vvvd = (received / total * 100).toStringAsFixed(0) + "%";// CircularProgressIndicator(value: currentProgress,) 进度 0-1currentProgress = received / total;});}});if (response.statusCode == 200) {print('正在下载...');}}catch(e){Response response = await dio.download(widget.cvv, "$nu.mp4",onReceiveProgress: (received, total) {if (total != -1) {///当前下载的百分比例setState(() {vvvd = (received / total * 100).toStringAsFixed(0) + "%";// CircularProgressIndicator(value: currentProgress,) 进度 0-1currentProgress = received / total;});}});if (response.statusCode == 200) {print('正在下载...');}}///获取手机的存储目录路径///getExternalStorageDirectory() 获取的是  android 的外部存储 (External Storage)///  getApplicationDocumentsDirectory 获取的是 ios 的Documents` or `Downloads` 目录}
//http://v.douyin.com/xGSE7P
}

解析接口直接用吧,不用重复造轮子

如果有兴趣的伙伴,可以将代码精简和优化,然后@我一份,

打包测试https://w333.lanzous.com/iyoHad8wd0b

,然后发现有几个问题,一解析后不重置,

而动态申请下载权限,只是进入应用管理页,并不是弹出授权页

好了,如果,你有好的建议,请@我

flutter 抖音无水印解析视频相关推荐

  1. php 记事本源代码_抖音无水印解析PHP源码

    抖音无水印解析PHP源码 仅限学习使用 输出为标准的格式化json数据 ajax直接调用即可 原生的ajax的调用方法看底部 $url = @$_GET['url']; if (strstr($url ...

  2. 最新抖音无水印解析PHP源码

    源码介绍: 最新抖音无水印解析PHP源码 网盘下载地址: http://www.bytepan.com/hQuJxMu7aaG 图片:

  3. 怎么在腾讯云函数抖音无水印解析接口部署

    使用腾讯云函数(SCF)部署抖音无水印接口调用代码,无需服务器,稳定安全可靠! 示例接口返回数据请求: https://service-eu6l8yx0-1256101469.gz.apigw.ten ...

  4. python 抖音评论_新手python抖音无水印解析带详细注释

    资源来源网络,如果需要授权,请大家更换源码,模块仅供学习,如需商用请购买正版授权,本栏目不提供技术服务,积分不够请签到,或者会员中心投稿源码 注释都很详细,可以看看注释!友情提醒,仅供学习使用,请勿用 ...

  5. php抖音跳转地址,PHP抖音无水印解析api

    输出标准的格式化了的json格式,ajax直接调用,调用地址/url=抖音地址 主要内容都输出了,status为1输出成功. ps:要网站输出视频必须支持https $url = @$_GET['ur ...

  6. PHP抖音无水印解析api

    输出标准的格式化了的json格式,ajax直接调用,调用地址/url=抖音地址 主要内容都输出了,status为1输出成功. ps:要网站输出视频必须支持https <?php $url = @ ...

  7. 百度SEO抖音无水印解析网站源码

    上传到主机解压 不用安装,直接打开域名就可以了 下载地址: http://www.bytepan.com/ekNSvXgncyt

  8. 抖音无水印解析网站精美源码-无需数据库 安装

    介绍: 上传到主机解压 不用安装,直接打开域名就可以了 网盘下载地址: https://zijiewangpan.com/Gch7wb8f8uP 图片:

  9. Java 抖音无水印解析

    1.直接导入第三方jar <dependency><groupId>commons-httpclient</groupId><artifactId>co ...

最新文章

  1. mysql索引详解_MySQL索引详解
  2. 学会数据库读写分离、分表分库
  3. python import 路径_Python 从相对路径下import的方法
  4. php5.2 zengd,大对杀狗狗再犯低级错误 ZEN狂输200目笑翻棋友
  5. golang的new函数_new()和make()函数以及Golang中的示例
  6. JAVA_JDK下载与安装教程(小白)
  7. attachEvent方法绑定事件
  8. VM虚拟机浏览器替代软件-VMLogin虚拟多登指纹浏览器,超级浏览器,防关联浏览器
  9. xmind2020激活教程_思维导图软件XMind 2020 v10.2.1中文版的官网下载、安装与序列号注册文件激活教程-推荐实用小软件 -亦是美网络...
  10. 云计算网络基础架构的实践和演进
  11. Juniper 防火墙JSRP高可用性HA(High Availability) chassis cluster双击冗余
  12. 基于STM32单片机智能手环脉搏心率检测计步器原理图PCB
  13. The remote end hung up unexpectedly The remote end hung up unexpectedly RPC failed;
  14. 微信小程序入门与实战之阅读列表与setData数据的绑定
  15. 2018年11月TIOBE编程语言排行榜,Java稳居第一
  16. 亚马逊高管为何频繁离职
  17. BATCH: A Scalable Asymmetric DiscreteCross-Modal Hashing--文献翻译
  18. 释放低代码原力,用友YonBuilder助力太湖云打造多云管理平台
  19. 【诗经】之《秦风·无衣》
  20. 【利用Advanced Installer 进行Springboot 打jar包部署】

热门文章

  1. meate30pro刷鸿蒙,华为Mate40E和mate30pro哪个好-参数对比测评
  2. mysql中国菜刀连接_中国菜刀(Chopper)详细剖析
  3. CreateFile 函数详解
  4. E - 18岁生日(20)
  5. 全网通手机插联通卡不显示无服务器,无sim卡是怎么回事
  6. IBM认知计算体系课程笔记
  7. 认知计算主义的重建与反思
  8. 在线英语词典翻译系统
  9. bpcs uploader.php,linux 百度云bpcs_uploader上传 下载 删除等操作
  10. 如何查看网页端所占的内存大小