第二篇-用Flutter手撸一个抖音国内版,看看有多炫

前言

继上一篇使用Flutter开发的抖音国际版后再次撸一个国内版抖音,大部分功能已完成,主要是Flutter开发APP速度很爽,  先看下图


项目主要结构介绍


 这次主要的改动在api.dart 及douyin.dart里,国内抖音的api是不同的,另外地址以及实体类也不一样。详细下面介绍.

抖音的实体类

主要是讲json转化为实体模型,然后绑定到view 层面,写这个实体类还是很耗费时间的,毕竟得先用爬网知识讲抖音的json拿到,并且根据json反向写实体类.

这个地址获取到抖音的推荐列表json: https://creator.douyin.com/aweme/v1/creator/data/billboard/?billboard_type=4,绑定第一个Douyin实体,拿到所有抖音的url地址


通过第二个api地址 https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids= 拿到抖音视频所有的json信息并且绑定VideoData实体类

class Douyin {

  int statusCode;

  String statusMsg;

  List billboardData;

  Extra extra;


  Douyin({this.statusCode, this.statusMsg, this.billboardData, this.extra});


  Douyin.fromJson(Map json) {

    statusCode = json["status_code"];

    statusMsg = json["status_msg"];

    if (json['billboard_data'] != null) {

      billboardData = new List();

      json["billboard_data"].forEach((v) {

        billboardData.add(BillboardData.fromJson(v));

      });

    }

    extra = json['extra'] != null ? new Extra.fromJson(json['extra']) : null;

  }


  Map toJson() {

    final Map data = new Map();

    data["status_code"] = this.statusCode;

    data["status_msg"] = this.statusMsg;

    if (this.billboardData != null) {

      data["billboard_data"] =

          this.billboardData.map((v) => v.toJson()).toList();

    }

    data["extra"] = this.extra;

    return data;

  }

}


class BillboardData {

  String author;

  String imgUrl;

  String link;

  int rank;

  String title;

  String value;


  BillboardData(

      {this.author, this.imgUrl, this.link, this.rank, this.title, this.value});


  BillboardData.fromJson(Map json) {

    this.author = json["author"];

    this.imgUrl = json["img_url"];

    this.link = json["link"];

    this.rank = json["rank"];

    this.title = json["title"];

    this.value = json["value"];

  }


  Map toJson() {

    final Map data = new Map();

    data["author"] = this.author;

    data["img_url"] = this.imgUrl;

    data["link"] = this.link;

    data["rank"] = this.rank;

    data["title"] = this.title;

    data["value"] = this.value;

    return data;

  }

}


class Extra {

  int now;

  Extra({this.now});


  Extra.fromJson(Map json) {

    now = json["now"];

  }


  Map toJson() {

    final Map data = new Map();

    data["now"] = this.now;

    return data;

  }

}


class VideoData {

  int statusCode;

  List itemList;

  ExtraData extra;


  VideoData.fromJson(Map json) {

    this.statusCode = json["status_code"];

    if (json['item_list'] != null) {

      itemList = new List();

      json['item_list'].forEach((v) {

        itemList.add(new Itemlist.fromJson(v));

      });

    }

    this.extra =

        json["extra"] != null ? new ExtraData.fromJson(json["extra"]) : null;

  }


  Map toJson() {

    final Map data = new Map();

    data["status_code"] = this.statusCode;

    if (this.itemList != null) {

      data['item_list'] = this.itemList.map((v) => v.toJson()).toList();

    }

    if (this.extra != null) {

      data["extra"] = this.extra.toJson();

    }

    return data;

  }

}


class Itemlist {

  String awemeid;

  String videolabels;

  String labeltoptext;

  int category;

  Author author;

  int duration;

  String promotions;

  int ispreview;

  int createtime;

  List chalist;

  String commentlist;

  int authoruserid;

  String videotext;

  int groupid;

  bool islivereplay;

  ShareInfo shareinfo;

  String position;

  String imageinfos;

  RiskInfos riskinfos;

  String uniqidposition;

  String geofencing;

  Statistics statistics;

  int awemetype;

  Music music;

  List textExtras;

  Video video;

  String shareurl;

  String desc;

  String longvideo;


  Itemlist(

      {this.awemeid,

      this.videolabels,

      this.labeltoptext,

      this.category,

      this.author,

      this.duration,

      this.promotions,

      this.ispreview,

      this.createtime,

      this.chalist,

      this.commentlist,

      this.authoruserid,

      this.videotext,

      this.groupid,

      this.islivereplay,

      this.shareinfo,

      this.position,

      this.imageinfos,

      this.riskinfos,

      this.uniqidposition,

      this.geofencing,

      this.statistics,

      this.awemetype,

      this.music,

      this.textExtras,

      this.video,

      this.shareurl,

      this.desc,

      this.longvideo});


  Itemlist.fromJson(Map json) {

    this.awemeid = json["aweme_id"];

    this.videolabels = json["video_labels"];

    this.labeltoptext = json["label_top_text"];

    this.category = json["category"];

    this.author =

        json["author"] != null ? new Author.fromJson(json["author"]) : null;

    this.duration = json["duration"];

    this.promotions = json["promotions"];

    this.ispreview = json["is_preview"];

    this.createtime = json["create_time"];

    if (json["cha_list"] != null) {

      this.chalist = new List();

      json["cha_list"].forEach((v) {

        this.chalist.add(new ChaList.fromJson(v));

      });

    }

    this.commentlist = json["comment_list"];

    this.authoruserid = json["author_user_id"];

    this.videotext = json["video_text"];

    this.groupid = json["group_id"];

    this.islivereplay = json["is_live_replay"];

    this.shareinfo = json["share_info"] != null

        ? new ShareInfo.fromJson(json["share_info"])

        : null;

    this.position = json["position"];

    this.imageinfos = json["image_infos"];

    this.riskinfos = json["risk_infos"] != null

        ? new RiskInfos.fromJson(json["risk_infos"])

        : null;

    this.uniqidposition = json["uniqid_position"];

    this.geofencing = json["geofencing"];

    this.statistics = json["statistics"] != null

        ? new Statistics.fromJson(json["statistics"])

        : null;

    this.awemetype = json["aweme_type"];

    this.music =

        json["music"] != null ? new Music.fromJson(json["music"]) : null;

    if (json["text_extra"] != null) {

      this.textExtras = new List();

      json['text_extra'].forEach((v) {

        textExtras.add(new TextExtra.formJson(v));

      });

    }

    this.video =

        json["video"] != null ? new Video.fromJson(json["video"]) : null;

    this.shareurl = json["share_url"];

    this.desc = json["desc"];

    this.longvideo = json["long_video"];

  }


  Map toJson() {

    final Map data = new Map();

    data["aweme_id"] = this.awemeid;

    data["video_labels"] = this.videolabels;

    data["label_top_text"] = this.labeltoptext;

    data["category"] = this.category;

    if (this.author != null) {

      data["author"] = this.author.toJson();

    }

    data["duration"] = this.duration;

    data["promotions"] = this.promotions;

    data["is_preview"] = this.ispreview;

    data["create_time"] = this.createtime;

    if (this.chalist != null) {

      data["cha_list"] = this.chalist.map((e) => e.toJson()).toList();

    }

    data["comment_list"] = this.commentlist;

    data["author_user_id"] = this.authoruserid;

    data["video_text"] = this.videotext;

    data["group_id"] = this.groupid;

    data["is_live_replay"] = this.islivereplay;

    if (this.shareinfo != null) {

      data["share_info"] = this.shareinfo.toJson();

    }

    data["position"] = this.position;

    data["image_infos"] = this.imageinfos;

    if (this.riskinfos != null) {

      data["risk_infos"] = this.riskinfos.toJson();

    }

    data["uniqid_position"] = this.uniqidposition;

    data["geofencing"] = this.geofencing;

    if (this.statistics != null) {

      data["statistics"] = this.statistics.toJson();

    }

    data["aweme_type"] = this.awemetype;

    if (this.music != null) {

      data["music"] = this.music.toJson();

    }

    if (this.textExtras != null) {

      data["text_extra"] = this.textExtras.map((e) => e.toJson()).toList();

    }

    if (this.video != null) {

      data["video"] = this.video.toJson();

    }

    data["share_url"] = this.shareurl;

    data["desc"] = this.desc;

    data["long_video"] = this.longvideo;

    return data;

  }

}


class TextExtra {

  String hashtagName;

  int hashtagId;

  int start;

  int end;

  int type;


  TextExtra(

      {this.hashtagName, this.hashtagId, this.start, this.end, this.type});


  TextExtra.formJson(Map json) {

    this.hashtagName = json["hashtag_name"];

    this.hashtagId = json["hashtag_id"];

    this.start = json["start"];

    this.end = json["end"];

    this.type = json["type"];

  }


  Map toJson() {

    final Map data = new Map();

    data["hashtag_name"] = this.hashtagName;

    data["hashtag_id"] = this.hashtagId;

    data["start"] = this.start;

    data["end"] = this.end;

    data["type"] = this.type;

    return data;

  }

}


// Author

class Author {

  String geofencing;

  String uid;

  String shortID;

  String signature;

  AvatarMedium avatarMedium;

  String uniqueId;

  String followersDetail;

  String platformSyncInfo;

  String policyVersion;

  String nickname;

  AvatarLarger avatarlarger;

  AvatarThumb avatarthumb;


  Author(

      {this.geofencing,

      this.uid,

      this.shortID,

      this.signature,

      this.avatarMedium,

      this.uniqueId,

      this.followersDetail,

      this.platformSyncInfo,

      this.policyVersion,

      this.nickname,

      this.avatarlarger,

      this.avatarthumb});


  Author.fromJson(Map json) {

    this.geofencing = json["geofencing"];

    this.uid = json["uid"];

    this.shortID = json["short_id"];

    this.signature = json["signature"];

    this.avatarMedium = json["avatar_medium"] != null

        ? new AvatarMedium.fromJson(json["avatar_medium"])

        : null;

    this.uniqueId = json["unique_id"];

    this.followersDetail = json["followers_detail"];

    this.platformSyncInfo = json["platform_sync_info"];

    this.policyVersion = json["policy_version"];

    this.nickname = json["nickname"];

    this.avatarlarger = json["avatar_larger"] != null

        ? new AvatarLarger.formJson(json["avatar_larger"])

        : null;

    this.avatarthumb = json["avatar_thumb"] != null

        ? new AvatarThumb.formJson(json["avatar_thumb"])

        : null;

  }


  Map toJson() {

    final Map data = new Map();

    data["geofencing"] = this.geofencing;

    data["uid"] = this.uid;

    data["short_id"] = this.shortID;

    data["signature"] = this.signature;

    if (this.avatarMedium != null) {

      data["avatar_medium"] = this.avatarMedium.toJson();

    }

    data["unique_id"] = this.uniqueId;

    data["followers_detail"] = this.followersDetail;

    data["platform_sync_info"] = this.platformSyncInfo;

    data["policy_version"] = this.policyVersion;

    data["nickname"] = this.nickname;

    if (this.avatarlarger != null) {

      data["avatar_larger"] = this.avatarlarger.toJson();

    }

    if (this.avatarthumb != null) {

      data["avatar_thumb"] = this.avatarthumb.toJson();

    }

    return data;

  }

}


class AvatarMedium {

  List urlList;

  String uri;

  AvatarMedium({this.urlList, this.uri});


  AvatarMedium.fromJson(Map json) {

    if (json["url_list"] != null) {

      this.urlList = json["url_list"].cast();

    }

    this.uri = json["uri"];

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    return data;

  }

}


class AvatarLarger {

  String uri;

  List urlList;

  AvatarLarger({this.uri, this.urlList});


  AvatarLarger.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class AvatarThumb {

  String uri;

  List urlList;

  AvatarThumb({this.uri, this.urlList});


  AvatarThumb.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class ExtraData {

  int now;

  String logid;

  ExtraData({this.now, this.logid});


  ExtraData.fromJson(Map json) {

    this.now = json["now"];

    this.logid = json["logid"];

  }


  Map toJson() {

    final Map data = new Map();

    data["now"] = this.now;

    data["logid"] = this.logid;

    return data;

  }

}

//End author


//ChaList

class ChaList {

  String chaName;

  int viewCount;

  String hashTagProfile;

  bool isCommerce;

  String cid;

  String desc;

  int userCount;

  String connectMusic;

  int type;

  CoverItem coverItem;

  ChaList(

      {this.chaName,

      this.viewCount,

      this.hashTagProfile,

      this.isCommerce,

      this.cid,

      this.desc,

      this.userCount,

      this.connectMusic,

      this.type,

      this.coverItem});


  ChaList.fromJson(Map json) {

    this.chaName = json["cha_name"];

    this.viewCount = json["view_count"];

    this.hashTagProfile = json["hash_tag_profile"];

    this.isCommerce = json["is_commerce"];

    this.cid = json["cid"];

    this.desc = json["desc"];

    this.userCount = json["user_count"];

    this.connectMusic = json["connect_music"];

    this.type = json["type"];

    this.coverItem = json["cover_item"] != null

        ? new CoverItem.formJson(json["cover_item"])

        : null;

  }


  Map toJson() {

    final Map data = new Map();

    data["cha_name"] = this.chaName;

    data["view_count"] = this.viewCount;

    data["hash_tag_profile"] = this.hashTagProfile;

    data["is_commerce"] = this.isCommerce;

    data["cid"] = this.cid;

    data["desc"] = this.desc;

    data["user_count"] = this.userCount;

    data["connect_music"] = this.connectMusic;

    data["type"] = this.type;

    if (this.coverItem != null) {

      data["cover_item"] = this.coverItem.toJson();

    }

    return data;

  }

}


class CoverItem {

  String uri;

  List urlList;

  CoverItem({this.uri, this.urlList});

  CoverItem.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}

//End ChaList


//ShareInfo

class ShareInfo {

  String shareweibodesc;

  String sharedesc;

  String sharetitle;

  ShareInfo({this.shareweibodesc, this.sharedesc, this.sharetitle});

  ShareInfo.fromJson(Map json) {

    this.shareweibodesc = json["share_weibo_desc"];

    this.sharedesc = json["share_desc"];

    this.sharetitle = json["share_title"];

  }

  Map toJson() {

    final Map data = new Map();

    data["share_weibo_desc"] = this.shareweibodesc;

    data["share_desc"] = this.sharedesc;

    data["share_title"] = this.sharetitle;

    return data;

  }

}

//End ShareInfo


//RiskInfos

class RiskInfos {

  bool warn;

  int type;

  String content;

  RiskInfos({this.warn, this.type, this.content});

  RiskInfos.fromJson(Map json) {

    this.warn = json["warn"] as bool;

    this.type = json["type"];

    this.content = json["content"];

  }

  Map toJson() {

    final Map data = new Map();

    data["warn"] = this.warn;

    data["type"] = this.type;

    data["content"] = this.content;

    return data;

  }

}

//End RiskInfos


//Statistics

class Statistics {

  String awemeId;

  int commentCount;

  int diggCount;

  Statistics.fromJson(Map json) {

    this.awemeId = json["aweme_id"];

    this.commentCount = json["comment_count"];

    this.diggCount = json["digg_count"];

  }

  Map toJson() {

    final Map data = new Map();

    data["aweme_id"] = this.awemeId;

    data["comment_count"] = this.commentCount;

    data["digg_count"] = this.diggCount;

    return data;

  }

}

//End Statistics


//Music

class Music {

  CoverLarge coverlarge;

  CoverMedium covermedium;

  int duration;

  int status;

  String mid;

  String title;

  String author;

  PlayUrl playurl;

  String position;

  int id;

  CoverHd coverhd;

  CoverThumb coverthumb;


  Music.fromJson(Map json) {

    this.coverlarge = json["cover_large"] != null

        ? new CoverLarge.formJson(json["cover_large"])

        : null;

    this.covermedium = json["cover_medium"] != null

        ? new CoverMedium.formJson(json["cover_medium"])

        : null;

    this.duration = json["duration"];

    this.status = json["status"];

    this.mid = json["mid"];

    this.title = json["title"];

    this.author = json["author"];

    this.playurl = json["play_url"] != null

        ? new PlayUrl.formJson(json["play_url"])

        : null;

    this.position = json["position"];

    this.id = json["id"];

    this.coverhd = json["cover_hd"] != null

        ? new CoverHd.formJson(json["cover_hd"])

        : null;

    this.coverthumb = json["cover_thumb"] != null

        ? new CoverThumb.formJson(json["cover_thumb"])

        : null;

  }


  Map toJson() {

    final Map data = new Map();

    if (this.coverlarge != null) {

      data["cover_large"] = this.coverlarge.toJson();

    }

    if (this.covermedium != null) {

      data["cover_medium"] = this.covermedium.toJson();

    }

    data["duration"] = this.duration;

    data["status"] = this.status;

    data["mid"] = this.mid;

    data["title"] = this.title;

    data["author"] = this.author;

    if (this.playurl != null) {

      data["play_url"] = this.playurl.toJson();

    }

    data["position"] = this.position;

    data["id"] = this.id;

    if (this.coverhd != null) {

      data["cover_hd"] = this.coverhd.toJson();

    }

    if (this.coverthumb != null) {

      data["cover_thumb"] = this.coverthumb.toJson();

    }

    return data;

  }

}


class CoverLarge {

  String uri;

  List urlList;

  CoverLarge({this.uri, this.urlList});

  CoverLarge.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class CoverMedium {

  String uri;

  List urlList;

  CoverMedium({this.uri, this.urlList});

  CoverMedium.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class PlayUrl {

  String uri;

  List urlList;

  PlayUrl({this.uri, this.urlList});

  PlayUrl.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class CoverHd {

  String uri;

  List urlList;

  CoverHd({this.uri, this.urlList});

  CoverHd.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class CoverThumb {

  String uri;

  List urlList;

  CoverThumb({this.uri, this.urlList});

  CoverThumb.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}

//End Music


//Video

class Video {

  int width;

  OriginCover origincover;

  String ratio;

  bool haswatermark;

  String bitrate;

  PlayAddr playaddr;

  Cover cover;

  int duration;

  String vid;

  int islongvideo;

  int height;

  DynamicCover dynamiccover;

  Video(

      {this.width,

      this.origincover,

      this.ratio,

      this.haswatermark,

      this.bitrate,

      this.playaddr,

      this.cover,

      this.duration,

      this.vid,

      this.islongvideo,

      this.height,

      this.dynamiccover});

  Video.fromJson(Map json) {

    this.width = json["width"];

    this.origincover = json["origin_cover"] != null

        ? new OriginCover.formJson(json["origin_cover"])

        : null;

    this.ratio = json["ratio"];

    this.haswatermark = json["has_watermark"];

    this.bitrate = json["bit_rate"];

    this.playaddr = json["play_addr"] != null

        ? new PlayAddr.formJson(json["play_addr"])

        : null;

    this.cover =

        json["cover"] != null ? new Cover.formJson(json["cover"]) : null;

    this.duration = json["duration"];

    this.vid = json["vid"];

    this.islongvideo = json["is_long_video"];

    this.height = json["height"];

    this.dynamiccover = json["dynamic_cover"] != null

        ? new DynamicCover.formJson(json["dynamic_cover"])

        : null;

  }


  Map toJson() {

    final Map data = new Map();

    data["width"] = this.width;

    if (this.origincover != null) {

      data["origin_cover"] = this.origincover.toJson();

    }

    data["ratio"] = this.ratio;

    data["has_watermark"] = this.haswatermark;

    data["bit_rate"] = this.bitrate;

    if (this.playaddr != null) {

      data["play_addr"] = this.playaddr.toJson();

    }

    if (this.cover != null) {

      data["cover"] = this.cover.toJson();

    }

    data["duration"] = this.duration;

    data["vid"] = this.vid;

    data["is_long_video"] = this.islongvideo;

    data["height"] = this.height;

    if (this.dynamiccover != null) {

      data["dynamic_cover"] = this.dynamiccover.toJson();

    }

    return data;

  }

}


class OriginCover {

  String uri;

  List urlList;

  OriginCover({this.uri, this.urlList});

  OriginCover.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class PlayAddr {

  String uri;

  List urlList;

  PlayAddr({this.uri, this.urlList});

  PlayAddr.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class Cover {

  String uri;

  List urlList;

  Cover({this.uri, this.urlList});

  Cover.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


class DynamicCover {

  String uri;

  List urlList;

  DynamicCover({this.uri, this.urlList});

  DynamicCover.formJson(Map json) {

    this.uri = json["uri"] as String;

    this.urlList = json["url_list"].cast();

  }


  Map toJson() {

    final Map data = new Map();

    data["url_list"] = this.urlList;

    data["uri"] = this.uri;

    return data;

  }

}


//End Video

取抖音无水印视频,这里才是关键

通过这个api地址 https://aweme.snssdk.com/aweme/v1/play/?video_id={}&ratio=720p&line=0&media_type=4&vr_type=0&improve_bitrate=0&is_play_url=1&h265=1&adapt720=1 可以成功的拿到无水印视频,

此方法仅用于学习研究目的,不得从事违法活动哈,  否则与本作者无关.

具体实现代码如下

import 'dart:io';


import 'package:flutter/cupertino.dart';

import 'package:http/http.dart' as http;

import 'package:dio/dio.dart';


class RequestController {

  //static String host = "https://www.tiktok.com/";

  static String host = "https://creator.douyin.com";

  String url = host + "/aweme/v1/creator/data/billboard/?billboard_type=4";


  String video =

      "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=";


  String player = "https://aweme.snssdk.com/aweme/v1/play/?video_id=";


  Future getVideos() async {

    try {

      var response = await http.get(url);

      return response.body;

    } catch (e) {

      return e.toString();

    }

  }


  //获取无水印的视频

  Future getRedirects(String videoid) async {

    try {

      var response = await new Dio().get(

        player +

            videoid +

            "&ratio=720p&line=0&media_type=4&vr_type=0&improve_bitrate=0&is_play_url=1&h265=1&adapt720=1",

        options: Options(

            headers: headers,

            contentType: "text/html; charset=utf-8",

            followRedirects: false,

            validateStatus: (status) {

              return status < 500;

            }),

      );

      if (response.statusCode == 302) {

        return response.data.toString().split('"')[1];

      }

      return '';

    } catch (ex) {

      return '';

    }

  }


  Future getCookie() async {

    try {

      var response = await http.get(host + "/share/item/");

      return response.headers["set-cookie"];

    } catch (e) {

      return "error";

    }

  }


  var headers = {

    "user-agent":

        "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"

  };

}

剩下就是改造TrendingScreen里获取视频的方法 

getTrending() async {

  //var cookies = await api.getCookie();

  //api.setCookie(cookies);

  try {

    var response = await http.get(

      api.url,

      headers: api.headers,

    );

    Douyin tiktok = Douyin.fromJson(jsonDecode(response.body));

    tiktok.billboardData.forEach(

      (item) {

        setState(() {

          getVideos(item);

        });

      },

    );

  } catch (ex) {

    SimpleDialog(

      title: Text('Hot videos list is empty'),

    );

    print(ex);

  }

}

把获取到的无水印视频加载到view层

getVideos(BillboardData v) async {

    try {

      var url = v.link.split("/")[5];

      var response = await http.get(

        api.video + url + "&dytk",

        headers: api.headers,

      );

      VideoData videoData = VideoData.fromJson(jsonDecode(response.body));

      //获取无水印的视频地址

      api.getRedirects(videoData.itemList[0].video.playaddr.uri).then((url) => {

            print( Uri.decodeFull(url)),

            if (url != '')

              {

                videos.add(VideoItem(

                  data: videoData,

                  videourl: url,

                ))

              }

          });

    } catch (ex) {

      print(ex);

    }

  }

最后,就是绑定视频数据啦,大功告成!

Widget build(BuildContext context) {

  return Scaffold(

    body: Stack(

      children: [

        DouyinVideoPlayer(

          url: videourl,

        ),

        title(),

        VideoDescription(

          description: data.itemList[0].textExtras[0].hashtagName,

          musicName: data.itemList[0].music.title,

          authorName: data.itemList[0].music.author,

          userName: data.itemList[0].author.nickname,

        ),

        ActionsToolbar(

          comments: data.itemList[0].statistics.commentCount.toString(),

          userImg: data.itemList[0].author.avatarMedium.urlList[0],

          favorite: data.itemList[0].statistics.diggCount,

          coverImg: data.itemList[0].music.covermedium.urlList[0],

        ),

      ],

    ),

  );

}

结语

写到这里,手撸一个抖音app完成了基本功能,一些数据转化比喻点赞数还是原始int数据,需要转化成K M 等,后续待完善,毕竟花了一天时间来写这个app纯粹为了兴趣. 本人也极喜欢玩抖音.

另外因为写得匆忙,只测试了少量数据,json返回的数据有些为null ,也不知道具体是啥类型,这个待完善。 各位博友们觉得感兴趣的点个赞哈.  支持支持!


顺便说一下,各位支持的话点赞关注我继续完善剩余的部分,有需要学习了解的可以联系我,代码上传到github ,地址:https://github.com/WangCharlie/douyin,到这里就点个star, 谢谢.

你可能感兴趣的:(第二篇-用Flutter手撸一个抖音国内版,看看有多炫)