美文网首页程序员Flutter中文网
第二篇-用Flutter手撸一个抖音国内版,看看有多炫

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

作者: DTOK | 来源:发表于2020-05-24 23:35 被阅读0次

    前言

    继上一篇使用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> billboardData;

      Extra extra;

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

      Douyin.fromJson(Map<String, dynamic> json) {

        statusCode = json["status_code"];

        statusMsg = json["status_msg"];

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

          billboardData = new List<BillboardData>();

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

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

          });

        }

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> 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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

        now = json["now"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["now"] = this.now;

        return data;

      }

    }

    class VideoData {

      int statusCode;

      List<Itemlist> itemList;

      ExtraData extra;

      VideoData.fromJson(Map<String, dynamic> json) {

        this.statusCode = json["status_code"];

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

          itemList = new List<Itemlist>();

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

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

          });

        }

        this.extra =

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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> 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<TextExtra> 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<String, dynamic> 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<ChaList>();

          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<TextExtra>();

          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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

        this.hashtagName = json["hashtag_name"];

        this.hashtagId = json["hashtag_id"];

        this.start = json["start"];

        this.end = json["end"];

        this.type = json["type"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> 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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String> urlList;

      String uri;

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

      AvatarMedium.fromJson(Map<String, dynamic> json) {

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

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

        }

        this.uri = json["uri"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        return data;

      }

    }

    class AvatarLarger {

      String uri;

      List<String> urlList;

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

      AvatarLarger.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class AvatarThumb {

      String uri;

      List<String> urlList;

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

      AvatarThumb.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

        this.now = json["now"];

        this.logid = json["logid"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> 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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String> urlList;

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

      CoverItem.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

        this.shareweibodesc = json["share_weibo_desc"];

        this.sharedesc = json["share_desc"];

        this.sharetitle = json["share_title"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

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

        this.type = json["type"];

        this.content = json["content"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> json) {

        this.awemeId = json["aweme_id"];

        this.commentCount = json["comment_count"];

        this.diggCount = json["digg_count"];

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> 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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String> urlList;

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

      CoverLarge.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class CoverMedium {

      String uri;

      List<String> urlList;

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

      CoverMedium.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class PlayUrl {

      String uri;

      List<String> urlList;

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

      PlayUrl.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class CoverHd {

      String uri;

      List<String> urlList;

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

      CoverHd.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class CoverThumb {

      String uri;

      List<String> urlList;

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

      CoverThumb.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String, dynamic> 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<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String> urlList;

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

      OriginCover.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class PlayAddr {

      String uri;

      List<String> urlList;

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

      PlayAddr.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class Cover {

      String uri;

      List<String> urlList;

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

      Cover.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        data["url_list"] = this.urlList;

        data["uri"] = this.uri;

        return data;

      }

    }

    class DynamicCover {

      String uri;

      List<String> urlList;

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

      DynamicCover.formJson(Map<String, dynamic> json) {

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

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

      }

      Map<String, dynamic> toJson() {

        final Map<String, dynamic> data = new Map<String, dynamic>();

        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<String> getVideos() async {

        try {

          var response = await http.get(url);

          return response.body;

        } catch (e) {

          return e.toString();

        }

      }

      //获取无水印的视频

      Future<String> 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<String> 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: <Widget>[

            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手撸一个抖音国内版,看看有多炫

        本文链接:https://www.haomeiwen.com/subject/xqasahtx.html