httpuseragent

博客提供了一个网址http://www.httpuseragent.org/ ,但未给出该网址相关的更多信息技术方面的关键信息。

http://www.httpuseragent.org/

AccessLogUtils package chapter9 import com.alibaba.fastjson.{JSON, JSONObject} //拆分为拆分日期和时间 val arrCreateTime = timestamp.split("T") object AccessLogUtils { /** * 读取JSON,转换为AccessLog * * @param strAccessLog JSON 字符串 * @return AccessLog 对象 */ def read(strAccessLog: String): AccessLog = { //解析为JSONObject val jsonObj: JSONObject = JSON.parseObject(strAccessLog) //读取信息 val timestamp: String = jsonObj.getString("@timestamp") -4- = //日期 val createDate = arrCreateTime(0) //从时间中获取小时 val createHour ")(0).split(":")(0).toInt val host: String = jsonObj.getString("host") val clientip: String = jsonObj.getString("clientip") val request: String = jsonObj.getString("request") val httpUserAgent: String = jsonObj.getString("httpUserAgent") val size: Int = jsonObj.getIntValue("size") val responseTime: Float = jsonObj.getFloatValue("responsetime") val httpHost: String = jsonObj.getString("httpHost") val url: String = jsonObj.getString("url") val domain: String = jsonObj.getString("domain") val referer: String = jsonObj.getString("referer") val status: Int = jsonObj.getIntValue("status") //构造AccessLog 对象 AccessLog(timestamp,createDate, arrCreateTime(1).split(" env.readTextFile("data/access.log") //转换为AccessLog 对象 createHour,host, clientip, request, httpUserAgent, size, responseTime, httpHost, url, domain, referer, status) } } LogTest1 package chapter9 import org.apache.flink.streaming.api.scala._ import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment object LogTest1 { def main(args: Array[String]): Unit = { //创建运行环境 val env = StreamExecutionEnvironment.getExecutionEnvironment //设置并行度 env.setParallelism(1) //从文件中读取数据 val stream: DataStream[String] = -5- -6- val stream2: DataStream[AccessLog] = stream.map(json => { AccessLogUtils.read(json) }) // 创建表环境 val tableEnv = StreamTableEnvironment.create(env) // 将DataStream转换成表 val table = tableEnv.fromDataStream(stream2) //打印输出schema table.printSchema() //创建临时表 tableEnv.createTemporaryView("access_log", table) //计算每日PV val table2 = tableEnv.sqlQuery("select createDate, " + "count(*) as logCount " + "from access_log " + "group by createDate ") //打印输出流 tableEnv.toChangelogStream(table2).print() //开始执行 env.execute() } } LogTest2 package chapter9 import org.apache.flink.streaming.api.scala._ import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment object LogTest2 { def main(args: Array[String]): Unit = { //创建运行环境 val env = StreamExecutionEnvironment.getExecutionEnvironment //设置并行度 env.setParallelism(1) //从文件中读取数据 val stream: DataStream[String] = env.readTextFile("data/access.log") //转换为AccessLog对象 val stream2: DataStream[AccessLog] = stream.map(json => { -7- AccessLogUtils.read(json) }) // 创建表环境 val tableEnv = StreamTableEnvironment.create(env) // 将DataStream转换成表 val table = tableEnv.fromDataStream(stream2) //创建临时表 tableEnv.createTemporaryView("access_log", table) //状态码是500的数据 val table2 = tableEnv.sqlQuery("select * " + "from access_log " + "where status=500 ") //打印输出流 tableEnv.toChangelogStream(table2).print("status<>200") //响应时间过长 val table3 = tableEnv.sqlQuery("select * " + "from access_log " + "where responseTime>1 ") //打印输出流 tableEnv.toChangelogStream(table3).print("responseTime>1") //开始执行 env.execute() } } LogTest3 package chapter9 import org.apache.flink.streaming.api.scala._ import org.apache.flink.table.api.bridge.scala.StreamTableEnvironment object LogTest3 { def main(args: Array[String]): Unit = { //创建运行环境 val env = StreamExecutionEnvironment.getExecutionEnvironment //设置并行度 env.setParallelism(1) -8- //从文件中读取数据 val stream: DataStream[String] = env.readTextFile("data/access.log") //转换为AccessLog对象 val stream2: DataStream[AccessLog] = stream.map(json => { AccessLogUtils.read(json) }) // 创建表环境 val tableEnv = StreamTableEnvironment.create(env) // 将DataStream转换成表 val table = tableEnv.fromDataStream(stream2) //创建临时表 tableEnv.createTemporaryView("access_log", table) //每日响应时间分析 val table2 = tableEnv.sqlQuery("select createDate, " + "min(responseTime) as minResponseTime, " + "max(responseTime) as maxResponseTime, " + "avg(responseTime) as avgResponseTime " + "from access_log " + "where status=200 " + "group by createDate ") // 写入MySQL数据库中 val logTimeSql: String = """ |create table log_time ( | createDate varchar(10) not null, | minResponseTime float not null, | maxResponseTime float not null, | avgResponseTime float not null, | primary key (createDate) not enforced | ) with ( | 'connector.type' = 'jdbc', | 'connector.url' = 'jdbc:mysql://localhost:3306/flink_project?useSSL=false', | 'connector.table' = 'log_time', | 'connector.driver' = 'com.mysql.jdbc.Driver', | 'connector.username' = 'root', | 'connector.password' = 'root123456' | ) |""".stripMargin //执行SQL建表 tableEnv.executeSql(logTimeSql) //执行插入操作 table2.executeInsert("log_time") -9- // 转换成流打印输出 tableEnv.toChangelogStream(table2) .print() //每小时的流量分析 val table3 = tableEnv.sqlQuery("select createHour," + "sum(size) as totalSize, " + "avg(size) as avgSize " + "from access_log " + "where status=200 " + "group by createHour") // 写入MySQL数据库中 val logSizeSql: String = """ |create table log_size ( | createHour int not null, | totalSize bigint not null, | avgSize float not null, | primary key (createHour) not enforced | ) with ( | 'connector.type' = 'jdbc', | 'connector.url' = 'jdbc:mysql://localhost:3306/flink_project?useSSL=false', | 'connector.table' = 'log_size', | 'connector.driver' = 'com.mysql.jdbc.Driver', | 'connector.username' = 'root', | 'connector.password' = 'root123456' | ) |""".stripMargin //执行SQL建表 tableEnv.executeSql(logSizeSql) //执行插入操作 table3.executeInsert("log_size") // 转换成流打印输出 tableEnv.toChangelogStream(table3) .print() //开始执行 env.execute() } }3. 日志的分析与实现 通过前两步可以得到网站日志文件,附件:access.log 其中包含的字段比较多,建议先定义样例类 AccessLog 用于表示网站日志, 其中包含如下字段: * 访问日志 * @param ts 时间戳 * @param host 主机名 * @param clientip 客户端 IP * @param request 请求 * @param httpUserAgent 用户代理 * @param size 请求的大小 * @param responseTime 响应时间 * @param httpHost 主机 * @param url URL * @param domain 域名 * @param referer 来源 * @param status 状态码 */ (1)访问量分析: a. 创建转换日志的工具类 AccessLogUtils,实现将 JSON 格式的字符串转 换为 AccessLog 对象。 b. 读取日志文件。日志文件中每行数据为 JSON 字符串,可以使用工具类 将 JSON 字符串转换为 AccessLog 对象。 c. 计算 PV。将上一步生成的 DataStream 转化为 Table 对象,执行 SQL 语句进行分组汇总,按照日期进行汇总,统计每组数据的数量,也就是 PV。 (2)异常日志分析 在日志中可以对异常情况进行分析。 a. 根据 HTTP 协议响应的状态码判断是否是异常日志。 正常返回结果的状态码是 200,服务器异常返回的状态码是 500,客户端请 求 URL 出现错误的状态码是 404。查询状态码是 500 的日志,也就是服务器 异常的日志,对于异常日志要实时监控处理。 b. 根据用户请求的响应时间判断是否是异常日志。定义响应时间超过 1 秒 就是异常日志。 (3)聚合分析 a. 连接 MySQL 数据库,创建数据表,并保存分析结果。对日志的响应时 间进行聚合分析,统计每日最小响应时间、最大响应时间及平均响应时间. b. 对日志的流量进行聚合分析,统计每小时总的字节数、平均字节数。 c. 对每日响应时间进行分析。按照日期进行分组统计,计算响应时间的最小 值、最大值和平均值。 c. 以小时为单位对日志的流量进行统计。 e.将以上聚合结果写入 log_time 表中。
06-23
日志的分析与实现 通过前两步可以得到网站日志文件,附件:access.log 其中包含的字段比较多,建议先定义样例类 AccessLog 用于表示网站日志, 其中包含如下字段: * 访问日志 * @param ts 时间戳 * @param host 主机名 * @param clientip 客户端 IP * @param request 请求 * @param httpUserAgent 用户代理 * @param size 请求的大小 * @param responseTime 响应时间 * @param httpHost 主机 * @param url URL * @param domain 域名 * @param referer 来源 * @param status 状态码 */ (1)访问量分析: a. 创建转换日志的工具类 AccessLogUtils,实现将 JSON 格式的字符串转 换为 AccessLog 对象。 b. 读取日志文件。日志文件中每行数据为 JSON 字符串,可以使用工具类 将 JSON 字符串转换为 AccessLog 对象。 c. 计算 PV。将上一步生成的 DataStream 转化为 Table 对象,执行 SQL 语句进行分组汇总,按照日期进行汇总,统计每组数据的数量,也就是 PV。 (2)异常日志分析 在日志中可以对异常情况进行分析。 a. 根据 HTTP 协议响应的状态码判断是否是异常日志。 正常返回结果的状态码是 200,服务器异常返回的状态码是 500,客户端请 求 URL 出现错误的状态码是 404。查询状态码是 500 的日志,也就是服务器 异常的日志,对于异常日志要实时监控处理。 b. 根据用户请求的响应时间判断是否是异常日志。定义响应时间超过 1 秒 就是异常日志。 (3)聚合分析 a. 连接 MySQL 数据库,创建数据表,并保存分析结果。对日志的响应时 间进行聚合分析,统计每日最小响应时间、最大响应时间及平均响应时间. b. 对日志的流量进行聚合分析,统计每小时总的字节数、平均字节数。 c. 对每日响应时间进行分析。按照日期进行分组统计,计算响应时间的最小 值、最大值和平均值。 c. 以小时为单位对日志的流量进行统计。 e.将以上聚合结果写入 log_time 表中。
06-23
网站日志实时分析系统的分析与实现 1. 使用 Flume 实现网站日志收集(可跳过) Flume 是一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的 系统。Flume 支持在日志系统中定制各类数据发送方,用于收集日志数据的收集和传输。 Flume 处理流程由 Source(数据源)、Channel(通道)和 Sink(输出) 组成。“数 据源”是指数据的来源和方式,本项目中数据来源是指定目录下的日志文件, 通道是对数据进行缓冲的缓冲池,可以使用内存或者文件系统实 现。“Sink” 定义了数据输出的方式和目的地,可以将数据输出到 HDFS、 Kafka 等外部 存储系统中。 2. Flume 与 Kafka 集成(可跳过) Flume 与 Kafka 集成可以采用两种方式实现:一种方式是 Kafka 作为 Flume 的通道,这种情况下,不需要为 Flume 配置输出,因为这种方式配置最简单, 推荐使用这种方式;另一种方式是 Kafka 作为 Flume 的输出。 3. 日志的分析与实现 通过前两步可以得到网站日志文件,附件:access.log 其中包含的字段比较多,建议先定义样例类 AccessLog 用于表示网站日志, 其中包含如下字段: * 访问日志 * @param ts 时间戳 * @param host 主机名 * @param clientip 客户端 IP * @param request 请求 * @param httpUserAgent 用户代理 * @param size 请求的大小 * @param responseTime 响应时间 * @param httpHost 主机 * @param url URL * @param domain 域名 * @param referer 来源 * @param status 状态码 */(1)访问量分析: a. 创建转换日志的工具类 AccessLogUtils,实现将 JSON 格式的字符串转 换为 AccessLog 对象。 b. 读取日志文件。日志文件中每行数据为 JSON 字符串,可以使用工具类 将 JSON 字符串转换为 AccessLog 对象。 c. 计算 PV。将上一步生成的 DataStream 转化为 Table 对象,执行 SQL 语句进行分组汇总,按照日期进行汇总,统计每组数据的数量,也就是 PV。 (2)异常日志分析 在日志中可以对异常情况进行分析。 a. 根据 HTTP 协议响应的状态码判断是否是异常日志。 正常返回结果的状态码是 200,服务器异常返回的状态码是 500,客户端请 求 URL 出现错误的状态码是 404。查询状态码是 500 的日志,也就是服务器 异常的日志,对于异常日志要实时监控处理。 b. 根据用户请求的响应时间判断是否是异常日志。定义响应时间超过 1 秒 就是异常日志。 (3)聚合分析 a. 连接 MySQL 数据库,创建数据表,并保存分析结果。对日志的响应时 间进行聚合分析,统计每日最小响应时间、最大响应时间及平均响应时间. b. 对日志的流量进行聚合分析,统计每小时总的字节数、平均字节数。 c. 对每日响应时间进行分析。按照日期进行分组统计,计算响应时间的最小 值、最大值和平均值。 c. 以小时为单位对日志的流量进行统计。 e.将以上聚合结果写入 log_time 表中
06-23
package top.yogiczy.mytv.tv.ui.screensold.main.components import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.key import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import kotlinx.coroutines.launch import android.widget.Toast import android.content.Context import android.content.Intent import androidx.compose.runtime.remember import top.yogiczy.mytv.core.data.utils.Constants import top.yogiczy.mytv.core.data.utils.Logger import top.yogiczy.mytv.core.data.entities.actions.KeyDownAction import top.yogiczy.mytv.core.data.entities.channel.Channel import top.yogiczy.mytv.core.data.entities.channel.ChannelGroupList import top.yogiczy.mytv.core.data.entities.channel.ChannelGroupList.Companion.channelList import top.yogiczy.mytv.core.data.entities.channel.ChannelLine import top.yogiczy.mytv.core.data.entities.channel.ChannelList import top.yogiczy.mytv.core.data.entities.epg.Epg import top.yogiczy.mytv.core.data.entities.epg.EpgList import top.yogiczy.mytv.core.data.entities.epg.EpgList.Companion.match import top.yogiczy.mytv.core.data.entities.epg.EpgList.Companion.recentProgramme import top.yogiczy.mytv.core.data.entities.epg.EpgProgrammeReserveList import top.yogiczy.mytv.core.data.entities.iptvsource.IptvSourceList import top.yogiczy.mytv.core.data.repositories.epg.EpgRepository import top.yogiczy.mytv.core.data.repositories.iptv.IptvRepository import top.yogiczy.mytv.tv.ui.material.PopupContent import top.yogiczy.mytv.tv.ui.material.Snackbar import top.yogiczy.mytv.tv.ui.material.Visibility import top.yogiczy.mytv.tv.ui.material.popupable import top.yogiczy.mytv.tv.ui.screen.settings.SettingsSubCategories import top.yogiczy.mytv.tv.ui.screen.main.MainViewModel import top.yogiczy.mytv.tv.ui.screen.main.mainVM import top.yogiczy.mytv.tv.ui.screen.settings.SettingsViewModel import top.yogiczy.mytv.tv.ui.screen.settings.settingsVM import top.yogiczy.mytv.tv.ui.screensold.audiotracks.AudioTracksScreen import top.yogiczy.mytv.tv.ui.screensold.channel.ChannelNumberSelectScreen import top.yogiczy.mytv.tv.ui.screensold.channel.ChannelScreen import top.yogiczy.mytv.tv.ui.screensold.channel.ChannelTempScreen import top.yogiczy.mytv.tv.ui.screensold.channel.rememberChannelNumberSelectState import top.yogiczy.mytv.tv.ui.screensold.channelline.ChannelLineScreen import top.yogiczy.mytv.tv.ui.screensold.classicchannel.ClassicChannelScreen import top.yogiczy.mytv.tv.ui.screensold.datetime.DatetimeScreen import top.yogiczy.mytv.tv.ui.screensold.epg.EpgProgrammeProgressScreen import top.yogiczy.mytv.tv.ui.screensold.epg.EpgScreen import top.yogiczy.mytv.tv.ui.screensold.epgreverse.EpgReverseScreen import top.yogiczy.mytv.tv.ui.screensold.quickop.QuickOpScreen import top.yogiczy.mytv.tv.ui.screensold.subtitletracks.SubtitleTracksScreen import top.yogiczy.mytv.tv.ui.screensold.iptvsource.IptvSourceScreen import top.yogiczy.mytv.tv.ui.screensold.videoplayer.VideoPlayerScreen import top.yogiczy.mytv.tv.ui.screensold.videoplayer.player.VideoPlayer import top.yogiczy.mytv.tv.ui.screensold.videoplayer.rememberVideoPlayerState import top.yogiczy.mytv.tv.ui.screensold.videoplayercontroller.VideoPlayerControllerScreen import top.yogiczy.mytv.tv.ui.screensold.videoplayerdiaplaymode.VideoPlayerDisplayModeScreen import top.yogiczy.mytv.tv.ui.screensold.videotracks.VideoTracksScreen import top.yogiczy.mytv.tv.ui.screensold.webview.WebViewScreen import top.yogiczy.mytv.tv.ui.screensold.webview.WebViewScreen_X5 import top.yogiczy.mytv.tv.ui.utils.backHandler import top.yogiczy.mytv.tv.ui.utils.handleDragGestures import top.yogiczy.mytv.tv.ui.utils.handleKeyEvents import top.yogiczy.mytv.tv.ui.utils.Configs import top.yogiczy.mytv.tv.X5CorePreLoadService @Composable fun MainContent( modifier: Modifier = Modifier, isLoadingProvider: () -> Boolean = { false }, filteredChannelGroupListProvider: () -> ChannelGroupList = { ChannelGroupList() }, favoriteChannelListProvider: () -> ChannelList = { ChannelList() }, epgListProvider: () -> EpgList = { EpgList() }, settingsViewModel: SettingsViewModel = settingsVM, onChannelFavoriteToggle: (Channel) -> Unit = {}, toSettingsScreen: (SettingsSubCategories?) -> Unit = {}, toDashboardScreen: () -> Unit = {}, onReload: () -> Unit = {}, onBackPressed: () -> Unit = {}, ) { val isLoading = isLoadingProvider() val coroutineScope = rememberCoroutineScope() val log = remember { Logger.create("MainContent")} val videoPlayerState = rememberVideoPlayerState(defaultDisplayModeProvider = { settingsViewModel.videoPlayerDisplayMode }) val mainContentState = rememberMainContentState( videoPlayerState = videoPlayerState, channelGroupListProvider = filteredChannelGroupListProvider, favoriteChannelListProvider = favoriteChannelListProvider, ) val channelNumberSelectState = rememberChannelNumberSelectState { val idx = it.toInt() - 1 filteredChannelGroupListProvider().channelList.getOrNull(idx)?.let { channel -> mainContentState.changeCurrentChannel(channel) } } Box( modifier = modifier .popupable() .backHandler { onBackPressed() } .handleKeyEvents( onUp = { getKeyDownEvent(settingsViewModel.keyDownEventUp, settingsViewModel, mainContentState, isLoading) }, onDown = { getKeyDownEvent(settingsViewModel.keyDownEventDown, settingsViewModel, mainContentState, isLoading) }, onLeft = { getKeyDownEvent(settingsViewModel.keyDownEventLeft, settingsViewModel, mainContentState, isLoading) }, onRight = { getKeyDownEvent(settingsViewModel.keyDownEventRight, settingsViewModel, mainContentState, isLoading) }, onLongUp = { getKeyDownEvent(settingsViewModel.keyDownEventLongUp, settingsViewModel, mainContentState, isLoading) }, onSelect = { getKeyDownEvent(settingsViewModel.keyDownEventSelect, settingsViewModel, mainContentState, isLoading) }, onLongSelect = { getKeyDownEvent(settingsViewModel.keyDownEventLongSelect, settingsViewModel, mainContentState, isLoading) }, onSettings = { mainContentState.isQuickOpScreenVisible = true }, onLongLeft = { getKeyDownEvent(settingsViewModel.keyDownEventLongLeft, settingsViewModel, mainContentState, isLoading) }, onLongRight = { getKeyDownEvent(settingsViewModel.keyDownEventLongRight, settingsViewModel, mainContentState, isLoading) }, onLongDown = { getKeyDownEvent(settingsViewModel.keyDownEventLongDown, settingsViewModel, mainContentState, isLoading) }, onNumber = { channelNumberSelectState.input(it) }, ) .handleDragGestures( onSwipeDown = { getKeyDownEvent(KeyDownAction.ChangeCurrentChannelToPrev, settingsViewModel, mainContentState, isLoading) }, onSwipeUp = { getKeyDownEvent(KeyDownAction.ChangeCurrentChannelToNext, settingsViewModel, mainContentState, isLoading) }, onSwipeRight = { getKeyDownEvent(KeyDownAction.ChangeCurrentChannelLineIdxToPrev, settingsViewModel, mainContentState, isLoading) }, onSwipeLeft = { getKeyDownEvent(KeyDownAction.ChangeCurrentChannelLineIdxToNext, settingsViewModel, mainContentState, isLoading) }, ), ) { Visibility({ mainContentState.currentChannelLine?.hybridType != ChannelLine.HybridType.WebView }) { VideoPlayerScreen( state = videoPlayerState, showMetadataProvider = { settingsViewModel.debugShowVideoPlayerMetadata }, forceTextureView = false, ) } key(mainContentState.isInPlaybackMode) { Visibility({ mainContentState.currentChannelLine?.hybridType == ChannelLine.HybridType.WebView }) { mainContentState.currentChannelLine.let { log.i("当前频道$it, 播放链接: ${it.playableUrl}") val isX5Available = com.tencent.smtt.sdk.QbSdk.canLoadX5(LocalContext.current) if (settingsViewModel.webViewCore == Configs.WebViewCore.X5 && !isX5Available){ settingsViewModel.webViewCore = Configs.WebViewCore.SYSTEM Toast.makeText( LocalContext.current, "X5内核不可用,将进行初始化。已切换为系统内核", Toast.LENGTH_LONG ).show() preInitX5Core(LocalContext.current) } when (settingsViewModel.webViewCore) { Configs.WebViewCore.SYSTEM -> { WebViewScreen( urlProvider = { Pair( it.playbackUrl ?: it.url, it.httpUserAgent ?: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0" ) }, onVideoResolutionChanged = { width, height -> videoPlayerState.metadata = videoPlayerState.metadata.copy( video = (videoPlayerState.metadata.video ?: VideoPlayer.Metadata.Video()).copy( width = width, height = height, ), ) mainContentState.isTempChannelScreenVisible = false }, ) } Configs.WebViewCore.X5 -> { WebViewScreen_X5( urlProvider = { Pair( it.playbackUrl ?: it.url, it.httpUserAgent ?: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0" ) }, onVideoResolutionChanged = { width, height -> videoPlayerState.metadata = videoPlayerState.metadata.copy( video = (videoPlayerState.metadata.video ?: VideoPlayer.Metadata.Video()).copy( width = width, height = height, ), ) mainContentState.isTempChannelScreenVisible = false }, onSelect = { mainContentState.isChannelScreenVisible = true }, onLongSelect = { mainContentState.isQuickOpScreenVisible = true }, ) } } } } } } Visibility({ settingsViewModel.uiShowEpgProgrammePermanentProgress }) { EpgProgrammeProgressScreen( currentEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme ?: epgListProvider().recentProgramme( mainContentState.currentChannel )?.now }, videoPlayerCurrentPositionProvider = { videoPlayerState.currentPosition }, ) } Visibility({ !mainContentState.isTempChannelScreenVisible && !mainContentState.isChannelScreenVisible && !mainContentState.isIptvSourceScreenVisible && !mainContentState.isQuickOpScreenVisible && !mainContentState.isEpgScreenVisible && !mainContentState.isChannelLineScreenVisible && channelNumberSelectState.channelNumber.isEmpty() }) { DatetimeScreen(showModeProvider = { settingsViewModel.uiTimeShowMode }) } ChannelNumberSelectScreen(channelNumberProvider = { channelNumberSelectState.channelNumber }) Visibility({ mainContentState.isTempChannelScreenVisible && !mainContentState.isChannelScreenVisible && !mainContentState.isIptvSourceScreenVisible && !mainContentState.isQuickOpScreenVisible && !mainContentState.isEpgScreenVisible && !mainContentState.isChannelLineScreenVisible && !mainContentState.isVideoPlayerControllerScreenVisible && channelNumberSelectState.channelNumber.isEmpty() }) { ChannelTempScreen( channelProvider = { mainContentState.currentChannel }, channelLineIdxProvider = { mainContentState.currentChannelLineIdx }, recentEpgProgrammeProvider = { epgListProvider().recentProgramme(mainContentState.currentChannel) }, currentPlaybackEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme }, playerMetadataProvider = { videoPlayerState.metadata }, ) } PopupContent( visibleProvider = { mainContentState.isEpgScreenVisible }, onDismissRequest = { mainContentState.isEpgScreenVisible = false }, ) { EpgScreen( epgProvider = { epgListProvider().match(mainContentState.currentChannel) ?: Epg.empty( mainContentState.currentChannel ) }, epgProgrammeReserveListProvider = { EpgProgrammeReserveList(settingsViewModel.epgChannelReserveList.filter { it.channel == mainContentState.currentChannel.name }) }, supportPlaybackProvider = { mainContentState.supportPlayback() }, currentPlaybackEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme }, onEpgProgrammePlayback = { mainContentState.isEpgScreenVisible = false mainContentState.changeCurrentChannel( mainContentState.currentChannel, mainContentState.currentChannelLineIdx, it, ) }, onEpgProgrammeReserve = { programme -> mainContentState.reverseEpgProgrammeOrNot( mainContentState.currentChannel, programme ) }, onClose = { mainContentState.isEpgScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isIptvSourceScreenVisible }, onDismissRequest = { mainContentState.isIptvSourceScreenVisible = false }, ) { IptvSourceScreen( currentIptvSourceProvider = { settingsViewModel.iptvSourceCurrent }, iptvSourceListProvider = {settingsViewModel.iptvSourceList}, onIptvSourceChanged = { mainContentState.isIptvSourceScreenVisible = false settingsViewModel.iptvSourceCurrent = it settingsViewModel.iptvChannelGroupHiddenList = emptySet() settingsViewModel.iptvChannelLastPlay = Channel.EMPTY onReload() }, onClose = { mainContentState.isIptvSourceScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isChannelLineScreenVisible }, onDismissRequest = { mainContentState.isChannelLineScreenVisible = false }, ) { ChannelLineScreen( channelProvider = { mainContentState.currentChannel }, currentLineProvider = { mainContentState.currentChannelLine }, onLineSelected = { mainContentState.isChannelLineScreenVisible = false mainContentState.changeCurrentChannel( mainContentState.currentChannel, mainContentState.currentChannel.lineList.indexOf(it), ) }, onClose = { mainContentState.isChannelLineScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isVideoPlayerControllerScreenVisible }, onDismissRequest = { mainContentState.isVideoPlayerControllerScreenVisible = false }, ) { val threshold = 1000L * 60 * 60 * 24 * 365 val hour0 = -28800000L VideoPlayerControllerScreen( isVideoPlayerPlayingProvider = { videoPlayerState.isPlaying }, isVideoPlayerBufferingProvider = { videoPlayerState.isBuffering }, videoPlayerCurrentPositionProvider = { if (videoPlayerState.currentPosition >= threshold) videoPlayerState.currentPosition else hour0 + videoPlayerState.currentPosition }, videoPlayerDurationProvider = { if (videoPlayerState.currentPosition >= threshold) { val playback = mainContentState.currentPlaybackEpgProgramme if (playback != null) { playback.startAt to playback.endAt } else { val programme = epgListProvider().recentProgramme(mainContentState.currentChannel)?.now (programme?.startAt ?: hour0) to (programme?.endAt ?: hour0) } } else { hour0 to (hour0 + videoPlayerState.duration) } }, onVideoPlayerPlay = { videoPlayerState.play() }, onVideoPlayerPause = { videoPlayerState.pause() }, onVideoPlayerSeekTo = { videoPlayerState.seekTo(it) }, onClose = { mainContentState.isVideoPlayerControllerScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isVideoPlayerDisplayModeScreenVisible }, onDismissRequest = { mainContentState.isVideoPlayerDisplayModeScreenVisible = false }, ) { VideoPlayerDisplayModeScreen( currentDisplayModeProvider = { videoPlayerState.displayMode }, onDisplayModeChanged = { videoPlayerState.displayMode = it }, onApplyToGlobal = { mainContentState.isVideoPlayerDisplayModeScreenVisible = false settingsViewModel.videoPlayerDisplayMode = videoPlayerState.displayMode Snackbar.show("已应用到全局") }, onClose = { mainContentState.isVideoPlayerDisplayModeScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isVideoTracksScreenVisible }, onDismissRequest = { mainContentState.isVideoTracksScreenVisible = false }, ) { VideoTracksScreen( trackListProvider = { videoPlayerState.metadata.videoTracks }, onTrackChanged = { videoPlayerState.selectVideoTrack(it) mainContentState.isVideoTracksScreenVisible = false }, onClose = { mainContentState.isVideoTracksScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isAudioTracksScreenVisible }, onDismissRequest = { mainContentState.isAudioTracksScreenVisible = false }, ) { AudioTracksScreen( trackListProvider = { videoPlayerState.metadata.audioTracks }, onTrackChanged = { videoPlayerState.selectAudioTrack(it) mainContentState.isAudioTracksScreenVisible = false }, onClose = { mainContentState.isAudioTracksScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isSubtitleTracksScreenVisible }, onDismissRequest = { mainContentState.isSubtitleTracksScreenVisible = false }, ) { SubtitleTracksScreen( trackListProvider = { videoPlayerState.metadata.subtitleTracks }, onTrackChanged = { videoPlayerState.selectSubtitleTrack(it) mainContentState.isSubtitleTracksScreenVisible = false }, onClose = { mainContentState.isSubtitleTracksScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isQuickOpScreenVisible }, onDismissRequest = { mainContentState.isQuickOpScreenVisible = false }, ) { QuickOpScreen( currentChannelProvider = { mainContentState.currentChannel }, currentChannelLineIdxProvider = { mainContentState.currentChannelLineIdx }, currentChannelNumberProvider = { (filteredChannelGroupListProvider().channelList.indexOf(mainContentState.currentChannel) + 1).toString() }, epgListProvider = epgListProvider, currentPlaybackEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme }, videoPlayerMetadataProvider = { videoPlayerState.metadata }, videoPlayerIndicatorProvider = { mainContentState.currentChannelLine?.hybridType != ChannelLine.HybridType.WebView }, onShowIptvSource ={ mainContentState.isQuickOpScreenVisible = false mainContentState.isIptvSourceScreenVisible = true }, onShowEpg = { mainContentState.isQuickOpScreenVisible = false mainContentState.isEpgScreenVisible = true }, onShowChannelLine = { mainContentState.isQuickOpScreenVisible = false mainContentState.isChannelLineScreenVisible = true }, onShowVideoPlayerController = { mainContentState.isQuickOpScreenVisible = false mainContentState.isVideoPlayerControllerScreenVisible = true }, onShowVideoPlayerDisplayMode = { mainContentState.isQuickOpScreenVisible = false mainContentState.isVideoPlayerDisplayModeScreenVisible = true }, onShowVideoTracks = { mainContentState.isQuickOpScreenVisible = false mainContentState.isVideoTracksScreenVisible = true }, onShowAudioTracks = { mainContentState.isQuickOpScreenVisible = false mainContentState.isAudioTracksScreenVisible = true }, onShowSubtitleTracks = { mainContentState.isQuickOpScreenVisible = false mainContentState.isSubtitleTracksScreenVisible = true }, toSettingsScreen = { mainContentState.isQuickOpScreenVisible = false toSettingsScreen(it) }, toDashboardScreen = { mainContentState.isQuickOpScreenVisible = false toDashboardScreen() }, onClearCache = { settingsViewModel.iptvChannelLinePlayableHostList = emptySet() settingsViewModel.iptvChannelLinePlayableUrlList = emptySet() coroutineScope.launch { IptvRepository(settingsViewModel.iptvSourceCurrent).clearCache() EpgRepository(settingsViewModel.epgSourceCurrent).clearCache() Snackbar.show("缓存已清除,请重启应用") } }, onClose = { mainContentState.isQuickOpScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isChannelScreenVisible && !settingsViewModel.uiUseClassicPanelScreen }, onDismissRequest = { mainContentState.isChannelScreenVisible = false }, ) { ChannelScreen( channelGroupListProvider = filteredChannelGroupListProvider, favoriteChannelListProvider = favoriteChannelListProvider, currentChannelProvider = { mainContentState.currentChannel }, currentChannelLineIdxProvider = { mainContentState.currentChannelLineIdx }, showChannelLogoProvider = { settingsViewModel.uiShowChannelLogo }, onChannelSelected = { mainContentState.isChannelScreenVisible = false mainContentState.changeCurrentChannel(it) }, onChannelFavoriteToggle = onChannelFavoriteToggle, epgListProvider = epgListProvider, showEpgProgrammeProgressProvider = { settingsViewModel.uiShowEpgProgrammeProgress }, currentPlaybackEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme }, videoPlayerMetadataProvider = { videoPlayerState.metadata }, channelFavoriteEnabledProvider = { settingsViewModel.iptvChannelFavoriteEnable }, channelFavoriteListVisibleProvider = { settingsViewModel.iptvChannelFavoriteListVisible }, onChannelFavoriteListVisibleChange = { settingsViewModel.iptvChannelFavoriteListVisible = it }, onClose = { mainContentState.isChannelScreenVisible = false }, ) } PopupContent( visibleProvider = { mainContentState.isChannelScreenVisible && settingsViewModel.uiUseClassicPanelScreen }, onDismissRequest = { mainContentState.isChannelScreenVisible = false }, ) { ClassicChannelScreen( channelGroupListProvider = filteredChannelGroupListProvider, favoriteChannelListProvider = favoriteChannelListProvider, currentChannelProvider = { mainContentState.currentChannel }, currentChannelLineIdxProvider = { mainContentState.currentChannelLineIdx }, showChannelLogoProvider = { settingsViewModel.uiShowChannelLogo }, onChannelSelected = { mainContentState.isChannelScreenVisible = false mainContentState.changeCurrentChannel(it) }, onChannelFavoriteToggle = onChannelFavoriteToggle, epgListProvider = epgListProvider, epgProgrammeReserveListProvider = { EpgProgrammeReserveList(settingsViewModel.epgChannelReserveList) }, showEpgProgrammeProgressProvider = { settingsViewModel.uiShowEpgProgrammeProgress }, supportPlaybackProvider = { mainContentState.supportPlayback(it, null) }, currentPlaybackEpgProgrammeProvider = { mainContentState.currentPlaybackEpgProgramme }, onEpgProgrammePlayback = { channel, programme -> mainContentState.isChannelScreenVisible = false mainContentState.changeCurrentChannel(channel, null, programme) }, onEpgProgrammeReserve = { channel, programme -> mainContentState.reverseEpgProgrammeOrNot(channel, programme) }, videoPlayerMetadataProvider = { videoPlayerState.metadata }, channelFavoriteEnabledProvider = { settingsViewModel.iptvChannelFavoriteEnable }, channelFavoriteListVisibleProvider = { settingsViewModel.iptvChannelFavoriteListVisible }, onChannelFavoriteListVisibleChange = { settingsViewModel.iptvChannelFavoriteListVisible = it }, onClose = { mainContentState.isChannelScreenVisible = false }, ) } EpgReverseScreen( epgProgrammeReserveListProvider = { settingsViewModel.epgChannelReserveList }, onConfirmReserve = { reserve -> filteredChannelGroupListProvider().channelList.firstOrNull { it.name == reserve.channel } ?.let { mainContentState.changeCurrentChannel(it) } }, onDeleteReserve = { reserve -> settingsViewModel.epgChannelReserveList = EpgProgrammeReserveList(settingsViewModel.epgChannelReserveList - reserve) }, ) } /** * 初始化X5内核 */ private fun preInitX5Core(context: Context) { // Accept context as a parameter // 预加载x5内核 val intent = Intent(context, X5CorePreLoadService::class.java) X5CorePreLoadService.enqueueWork(context, intent) } private fun getKeyDownEvent(actionEvent: KeyDownAction, settingsViewModel: SettingsViewModel, mainContentState: MainContentState, isLoading: Boolean) { when (actionEvent) { KeyDownAction.ChangeCurrentChannelToNext -> { if (settingsViewModel.iptvChannelChangeFlip) mainContentState.changeCurrentChannelToPrev() else mainContentState.changeCurrentChannelToNext() } KeyDownAction.ChangeCurrentChannelToPrev -> { if (settingsViewModel.iptvChannelChangeFlip) mainContentState.changeCurrentChannelToNext() else mainContentState.changeCurrentChannelToPrev() } KeyDownAction.ChangeCurrentChannelLineIdxToPrev -> { if (mainContentState.currentChannel.lineList.size > 1) { mainContentState.changeCurrentChannel( mainContentState.currentChannel, mainContentState.currentChannelLineIdx - 1, ) } } KeyDownAction.ChangeCurrentChannelLineIdxToNext -> { if (mainContentState.currentChannel.lineList.size > 1) { mainContentState.changeCurrentChannel( mainContentState.currentChannel, mainContentState.currentChannelLineIdx + 1, ) } } KeyDownAction.ToIptvSourceScreen -> { mainContentState.isIptvSourceScreenVisible = true } KeyDownAction.ToChannelScreen -> { if (!isLoading) mainContentState.isChannelScreenVisible = true } KeyDownAction.ToQuickOpScreen -> { mainContentState.isQuickOpScreenVisible = true } KeyDownAction.ToEpgScreen -> { mainContentState.isEpgScreenVisible = true } KeyDownAction.ToChannelLineScreen -> { mainContentState.isChannelLineScreenVisible = true } KeyDownAction.ToVideoPlayerControllerScreen -> { mainContentState.isVideoPlayerControllerScreenVisible = true } } }请将以上代码转换为java
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值