Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
android_vedio
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
android
android_vedio
Commits
fa2428dd
Commit
fa2428dd
authored
Jul 17, 2023
by
jyx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加腾讯播放器依赖,更新播放器
parent
d23e5db4
Changes
34
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
2020 additions
and
464 deletions
+2020
-464
build.gradle
video/app/build.gradle
+4
-1
proguard-rules.pro
video/app/proguard-rules.pro
+5
-1
AndroidManifest.xml
video/app/src/main/AndroidManifest.xml
+7
-0
MintsApplication.java
...p/src/main/java/com/xinfu/helivideo/MintsApplication.java
+4
-1
LocalVedioManager.kt
...ain/java/com/xinfu/helivideo/manager/LocalVedioManager.kt
+3
-1
TXCSDKService.java
.../main/java/com/xinfu/helivideo/manager/TXCSDKService.java
+39
-0
TrackManager.java
...c/main/java/com/xinfu/helivideo/manager/TrackManager.java
+15
-6
TrackPresenter.java
...va/com/xinfu/helivideo/mvp/presenters/TrackPresenter.java
+35
-1
MainFragment.kt
...main/java/com/xinfu/helivideo/ui/fragment/MainFragment.kt
+0
-6
DramaApiDetailActivity.kt
.../java/com/xinfu/helivideo/video/DramaApiDetailActivity.kt
+3
-1
DrawDramaFragment.kt
.../main/java/com/xinfu/helivideo/video/DrawDramaFragment.kt
+0
-361
TxVideoActivity.kt
...rc/main/java/com/xinfu/helivideo/video/TxVideoActivity.kt
+284
-0
VideoBean.kt
.../app/src/main/java/com/xinfu/helivideo/video/VideoBean.kt
+0
-49
ConfigBean.java
...rc/main/java/com/xinfu/helivideo/video/tx/ConfigBean.java
+207
-0
PlayerManager.java
...main/java/com/xinfu/helivideo/video/tx/PlayerManager.java
+112
-0
SuperShortVideoView.java
...ava/com/xinfu/helivideo/video/tx/SuperShortVideoView.java
+235
-0
TXVideoBaseView.java
...in/java/com/xinfu/helivideo/video/tx/TXVideoBaseView.java
+255
-0
TXVodPlayerWrapper.java
...java/com/xinfu/helivideo/video/tx/TXVodPlayerWrapper.java
+190
-0
VideoModel.java
...rc/main/java/com/xinfu/helivideo/video/tx/VideoModel.java
+26
-0
AbsPlayerRecyclerViewAdapter.java
...ivideo/video/tx/adapter/AbsPlayerRecyclerViewAdapter.java
+52
-0
AbsViewHolder.java
...a/com/xinfu/helivideo/video/tx/adapter/AbsViewHolder.java
+12
-0
ShortVideoPlayAdapter.java
...nfu/helivideo/video/tx/adapter/ShortVideoPlayAdapter.java
+75
-0
TxVideoAdapter.kt
...va/com/xinfu/helivideo/video/tx/adapter/TxVideoAdapter.kt
+161
-0
player_short_video_time.xml
video/app/src/main/res/drawable/player_short_video_time.xml
+10
-0
player_thumb_view.xml
video/app/src/main/res/drawable/player_thumb_view.xml
+16
-0
player_video_seek_bar.xml
video/app/src/main/res/drawable/player_video_seek_bar.xml
+27
-0
activity_tx_video.xml
video/app/src/main/res/layout/activity_tx_video.xml
+63
-0
item_block_view.xml
video/app/src/main/res/layout/item_block_view.xml
+0
-10
item_video.xml
video/app/src/main/res/layout/item_video.xml
+22
-25
player_item_base_view.xml
video/app/src/main/res/layout/player_item_base_view.xml
+67
-0
player_item_short_video_play.xml
.../app/src/main/res/layout/player_item_short_video_play.xml
+80
-0
super_short_video_view.xml
video/app/src/main/res/layout/super_short_video_view.xml
+10
-0
player_pause.png
video/app/src/main/res/mipmap-xhdpi/player_pause.png
+0
-0
settings.gradle
video/settings.gradle
+1
-1
No files found.
video/app/build.gradle
View file @
fa2428dd
...
...
@@ -236,7 +236,7 @@ dependencies {
// 穿山甲聚合 接入【穿山甲、快手】
// 穿山甲
implementation
(
"com.pangle.cn:pangrowth-sdk:3.7.0.1"
)
{
implementation
(
"com.pangle.cn:pangrowth-sdk:3.7.0.1"
)
{
exclude
group:
'com.pangle.cn'
,
module:
'pangrowth-game-sdk'
exclude
group:
'com.pangle.cn'
,
module:
'pangrowth-novel-sdk'
exclude
group:
'com.pangle.cn'
,
module:
'pangrowth-luckycat-sdk'
...
...
@@ -246,6 +246,9 @@ dependencies {
exclude
group:
'com.tencent.mm.opensdk'
,
module:
'wechat-sdk-android'
}
// 腾讯播放器
implementation
"com.tencent.liteav:LiteAVSDK_Player:latest.release"
testImplementation
'junit:junit:4.13.2'
androidTestImplementation
'androidx.test.ext:junit:1.1.3'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.4.0'
...
...
video/app/proguard-rules.pro
View file @
fa2428dd
...
...
@@ -488,4 +488,8 @@
-keep class tv.danmaku.ijk.media.player.
*
* {*; }
-dontwarn tv.danmaku.ijk.media.player.*
-keep interface tv.danmaku.ijk.media.player.
*
* { *; }
\ No newline at end of file
-keep interface tv.danmaku.ijk.media.player.
*
* { *; }
# ======================= 腾讯播放器 END ================
-keep class com.tencent.
*
* { *; }
# ======================= 腾讯播放器 END ================
video/app/src/main/AndroidManifest.xml
View file @
fa2428dd
...
...
@@ -147,6 +147,13 @@
android:exported=
"false"
android:screenOrientation=
"portrait"
/>
<activity
android:name=
".video.TxVideoActivity"
android:exported=
"false"
android:hardwareAccelerated=
"true"
android:screenOrientation=
"portrait"
/>
<service
android:name=
".ui.service.UpdateService"
android:exported=
"true"
/>
...
...
video/app/src/main/java/com/xinfu/helivideo/MintsApplication.java
View file @
fa2428dd
...
...
@@ -12,6 +12,7 @@ import com.downloader.PRDownloader;
import
com.downloader.PRDownloaderConfig
;
import
com.xinfu.helivideo.ad.TTGroMoreAdManagerHolder
;
import
com.xinfu.helivideo.common.Constant
;
import
com.xinfu.helivideo.manager.TXCSDKService
;
import
com.xinfu.helivideo.manager.UmengManager
;
import
com.xinfu.helivideo.net.LoanService
;
import
com.xinfu.helivideo.net.V6Service
;
...
...
@@ -42,7 +43,7 @@ public class MintsApplication extends MultiDexApplication {
private
V6Service
v6Service
;
private
HttpProxyCacheServer
proxy
=
null
;
public
static
class
StaticParams
{
public
static
class
StaticParams
{
public
static
HttpProxyCacheServer
getProxy
()
{
MintsApplication
app
=
(
MintsApplication
)
MintsApplication
.
getContext
();
return
app
.
proxy
==
null
?
app
.
newProxy
()
:
app
.
proxy
;
...
...
@@ -97,6 +98,8 @@ public class MintsApplication extends MultiDexApplication {
TTGroMoreAdManagerHolder
.
init
(
this
);
TXCSDKService
.
init
(
this
);
// 判断应用是否在前台
ForegroundOrBackground
.
init
(
this
);
...
...
video/app/src/main/java/com/xinfu/helivideo/manager/LocalVedioManager.kt
View file @
fa2428dd
...
...
@@ -13,6 +13,7 @@ import com.xinfu.helivideo.mvp.model.VedioBean
import
com.xinfu.helivideo.utils.AppPreferencesManager
import
com.xinfu.helivideo.utils.ToastUtil
import
com.xinfu.helivideo.video.DramaApiDetailActivity
import
com.xinfu.helivideo.video.TxVideoActivity
import
com.xinfu.helivideo.video.VideoActivity
/**
...
...
@@ -94,7 +95,8 @@ object LocalVedioManager {
bundle
.
putString
(
Constant
.
VEDIO_BEAN
,
JsonUtil
.
toJson
(
data
))
bundle
.
putBoolean
(
Constant
.
VEDIO_NEXT
,
isPlayNext
)
bundle
.
putBoolean
(
Constant
.
VEDIO_THIRD
,
isThirdId
)
readyGo
(
activity
,
VideoActivity
::
class
.
java
,
bundle
)
// readyGo(activity, VideoActivity::class.java, bundle)
readyGo
(
activity
,
TxVideoActivity
::
class
.
java
,
bundle
)
}
else
{
requestDrama
(
activity
,
data
)
}
...
...
video/app/src/main/java/com/xinfu/helivideo/manager/TXCSDKService.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
manager
;
import
android.content.Context
;
import
com.tencent.rtmp.TXLiveBase
;
import
com.tencent.rtmp.TXLiveBaseListener
;
public
class
TXCSDKService
{
private
static
final
String
TAG
=
"TXCSDKService"
;
// 如何获取License? 请参考官网指引 https://cloud.tencent.com/document/product/454/34750
private
static
final
String
licenceUrl
=
"https://license.vod2.myqcloud.com/license/v2/1317803579_1/v_cube.license"
;
private
static
final
String
licenseKey
=
"87b2b95939cfe9949749a9bdc2e34702"
;
private
TXCSDKService
()
{
}
/**
* 初始化腾讯云相关sdk。
* SDK 初始化过程中可能会读取手机型号等敏感信息,需要在用户同意隐私政策后,才能获取。
*
* @param appContext The application context.
*/
public
static
void
init
(
Context
appContext
)
{
TXLiveBase
.
getInstance
().
setLicence
(
appContext
,
licenceUrl
,
licenseKey
);
TXLiveBase
.
setListener
(
new
TXLiveBaseListener
()
{
@Override
public
void
onUpdateNetworkTime
(
int
errCode
,
String
errMsg
)
{
if
(
errCode
!=
0
)
{
TXLiveBase
.
updateNetworkTime
();
}
}
});
TXLiveBase
.
updateNetworkTime
();
// 短视频licence设置
}
}
\ No newline at end of file
video/app/src/main/java/com/xinfu/helivideo/manager/TrackManager.java
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
manager
;
import
android.text.TextUtils
;
import
com.xinfu.helivideo.MintsApplication
;
import
com.xinfu.helivideo.mvp.model.VedioBean
;
import
com.xinfu.helivideo.mvp.presenters.TrackPresenter
;
...
...
@@ -47,13 +44,25 @@ public class TrackManager {
public
void
commitVedio
(
VedioBean
data
)
{
if
(
trackPresenter
!=
null
)
{
HashMap
<
String
,
Object
>
vo
=
new
HashMap
<>();
vo
.
put
(
"vedioIndex"
,
data
.
getSeeIndex
());
vo
.
put
(
"vedioId"
,
data
.
getVedioId
());
vo
.
put
(
"thirdId"
,
data
.
getThirdId
());
vo
.
put
(
"vedioIndex"
,
data
.
getSeeIndex
());
vo
.
put
(
"vedioId"
,
data
.
getVedioId
());
vo
.
put
(
"thirdId"
,
data
.
getThirdId
());
trackPresenter
.
commitVedio
(
vo
);
}
}
public
void
collect
(
String
vedioId
)
{
if
(
trackPresenter
!=
null
)
{
trackPresenter
.
collect
(
vedioId
);
}
}
public
void
cancelCollect
(
String
vedioId
)
{
if
(
trackPresenter
!=
null
)
{
trackPresenter
.
cancelCollect
(
vedioId
);
}
}
public
void
getMyInfo
()
{
if
(
trackPresenter
!=
null
)
{
trackPresenter
.
getMyInfo
();
...
...
video/app/src/main/java/com/xinfu/helivideo/mvp/presenters/TrackPresenter.java
View file @
fa2428dd
...
...
@@ -6,7 +6,6 @@ import com.google.gson.JsonObject;
import
com.xinfu.library.net.neterror.BaseSubscriber
;
import
com.xinfu.library.net.neterror.Throwable
;
import
com.xinfu.helivideo.MintsApplication
;
import
com.xinfu.helivideo.common.AppConfig
;
import
com.xinfu.helivideo.common.DeviceInfo
;
import
com.xinfu.helivideo.manager.AppHttpManager
;
import
com.xinfu.helivideo.manager.UserManager
;
...
...
@@ -157,4 +156,39 @@ public class TrackPresenter extends BaseTrackPresenter {
}
public
void
collect
(
String
vedioId
)
{
HashMap
vo
=
new
HashMap
<
String
,
Object
>();
vo
.
put
(
"vedioId"
,
vedioId
);
AppHttpManager
.
getInstance
(
loanApplication
)
.
call
(
loanService
.
collect
(
vo
),
new
BaseSubscriber
<
BaseResponse
<
JsonObject
>>()
{
@Override
public
void
onCompleted
()
{
}
@Override
public
void
onError
(
Throwable
e
)
{
}
});
}
public
void
cancelCollect
(
String
vedioId
)
{
HashMap
vo
=
new
HashMap
<
String
,
Object
>();
vo
.
put
(
"vedioId"
,
vedioId
);
AppHttpManager
.
getInstance
(
loanApplication
)
.
call
(
loanService
.
cancelCollect
(
vo
),
new
BaseSubscriber
<
BaseResponse
<
JsonObject
>>()
{
@Override
public
void
onCompleted
()
{
}
@Override
public
void
onError
(
Throwable
e
)
{
}
});
}
}
video/app/src/main/java/com/xinfu/helivideo/ui/fragment/MainFragment.kt
View file @
fa2428dd
...
...
@@ -24,15 +24,9 @@ import com.xinfu.helivideo.mvp.views.HomeView
import
com.xinfu.helivideo.ui.adapter.HomeVideoPageAdapter
import
com.xinfu.helivideo.ui.adapter.ImageTitleAdapter
import
com.xinfu.helivideo.ui.adapter.TopAdapter
import
com.xinfu.helivideo.ui.fragment.base.BaseFragment
import
com.xinfu.helivideo.ui.fragment.base.LazyLoadBaseFragment
import
com.xinfu.helivideo.video.VideoActivity
import
com.scwang.smartrefresh.layout.api.RefreshLayout
import
com.scwang.smartrefresh.layout.listener.OnRefreshListener
import
com.youth.banner.Banner
import
com.youth.banner.adapter.BannerImageAdapter
import
com.youth.banner.holder.BannerImageHolder
import
com.youth.banner.indicator.CircleIndicator
import
kotlinx.android.synthetic.main.fragment_main.*
import
java.util.*
import
kotlin.concurrent.schedule
...
...
video/app/src/main/java/com/xinfu/helivideo/video/DramaApiDetailActivity.kt
View file @
fa2428dd
...
...
@@ -32,6 +32,7 @@ import com.xinfu.helivideo.ui.widgets.DialogListener
import
com.xinfu.helivideo.ui.widgets.VideoEpisodeDialog
import
com.xinfu.helivideo.ui.widgets.VipCountDialog
import
com.xinfu.helivideo.utils.LogUtil
import
com.xinfu.library.utils.nodoubleclick.AntiShake
import
kotlinx.android.synthetic.main.drama_activity_api_detail.*
import
kotlinx.android.synthetic.main.drama_activity_api_detail.episode_tv
import
kotlinx.android.synthetic.main.drama_activity_api_detail.fm_bottom
...
...
@@ -119,6 +120,7 @@ class DramaApiDetailActivity : BaseActivity(), VideoEpisodeAdapter.OnEpisodeClic
videoPresenter
.
attachView
(
this
)
fm_bottom
.
setOnClickListener
{
if
(
AntiShake
.
check
(
it
.
id
))
return
@setOnClickListener
showEpisodeDialog
()
}
...
...
@@ -492,7 +494,7 @@ class DramaApiDetailActivity : BaseActivity(), VideoEpisodeAdapter.OnEpisodeClic
private
var
dialog
:
VideoEpisodeDialog
?
=
null
private
fun
showEpisodeDialog
()
{
if
(
mVedioBean
==
null
)
return
if
(
mVedioBean
==
null
&&
dialog
!=
null
&&
dialog
!!
.
isShowing
)
return
dialog
=
VideoEpisodeDialog
(
this
,
mVedioBean
,
object
:
DialogListener
()
{
override
fun
onClick
(
dialog
:
Dialog
?,
v
:
View
?)
{
...
...
video/app/src/main/java/com/xinfu/helivideo/video/DrawDramaFragment.kt
deleted
100644 → 0
View file @
d23e5db4
This diff is collapsed.
Click to expand it.
video/app/src/main/java/com/xinfu/helivideo/video/TxVideoActivity.kt
0 → 100644
View file @
fa2428dd
package
com.xinfu.helivideo.video
import
android.app.Dialog
import
android.os.Bundle
import
android.os.Handler
import
android.os.Looper
import
android.view.View
import
com.google.gson.Gson
import
com.xinfu.helivideo.R
import
com.xinfu.helivideo.ad.AdManager
import
com.xinfu.helivideo.ad.AdStatusListener
import
com.xinfu.helivideo.ad.NoPreAdManager
import
com.xinfu.helivideo.common.Constant
import
com.xinfu.helivideo.mvp.model.IndexList
import
com.xinfu.helivideo.mvp.model.IndexList.VedioEpisodeBean
import
com.xinfu.helivideo.mvp.model.VedioBean
import
com.xinfu.helivideo.mvp.model.VideoMultiItemEntity
import
com.xinfu.helivideo.mvp.presenters.VideoPresenter
import
com.xinfu.helivideo.mvp.views.VideoView
import
com.xinfu.helivideo.ui.activitys.VipActivity
import
com.xinfu.helivideo.ui.activitys.base.BaseActivity
import
com.xinfu.helivideo.ui.adapter.VideoEpisodeAdapter
import
com.xinfu.helivideo.ui.widgets.DialogListener
import
com.xinfu.helivideo.ui.widgets.VideoEpisodeDialog
import
com.xinfu.helivideo.ui.widgets.VipCountDialog
import
com.xinfu.helivideo.video.tx.adapter.TxVideoAdapter
import
com.xinfu.library.utils.nodoubleclick.AntiShake
import
kotlinx.android.synthetic.main.activity_tx_video.*
class
TxVideoActivity
:
BaseActivity
(),
View
.
OnClickListener
,
VideoView
,
VideoEpisodeAdapter
.
OnEpisodeClickListener
,
TxVideoAdapter
.
OnCustomChildClickListener
{
var
videos
=
ArrayList
<
VedioEpisodeBean
>()
private
var
dialog
:
VideoEpisodeDialog
?
=
null
private
val
videoPresenter
by
lazy
{
VideoPresenter
()
}
private
var
mVedioBean
:
VedioBean
?
=
null
private
var
indexBean
:
IndexList
?
=
null
private
var
isPlayNext
=
false
private
var
playIndex
=
1
override
fun
getContentViewLayoutID
()
=
R
.
layout
.
activity_tx_video
override
fun
initViewsAndEvents
()
{
videoPresenter
.
attachView
(
this
)
mVedioBean
?.
let
{
videoPresenter
.
getIndexList
(
""
+
it
.
vedioId
)
}
playIndex
=
if
(
isPlayNext
)
{
mVedioBean
!!
.
recommendIndex
}
else
{
mVedioBean
!!
.
seeIndex
-
1
}
if
(
playIndex
>
mVedioBean
!!
.
vedioTotal
)
playIndex
=
0
initView
()
}
override
fun
getBundleExtras
(
extras
:
Bundle
?)
{
val
json
=
extras
?.
getString
(
Constant
.
VEDIO_BEAN
)
isPlayNext
=
extras
?.
getBoolean
(
Constant
.
VEDIO_NEXT
,
false
)
==
true
mVedioBean
=
Gson
().
fromJson
(
json
,
VedioBean
::
class
.
java
)
super
.
getBundleExtras
(
extras
)
}
override
fun
isApplyKitKatTranslucency
()
=
false
override
fun
onResume
()
{
super
.
onResume
()
super_short_video_view
.
resume
()
}
override
fun
onPause
()
{
super
.
onPause
()
super_short_video_view
.
pause
()
}
override
fun
onDestroy
()
{
super_short_video_view
.
onDestroy
()
super
.
onDestroy
()
super_short_video_view
.
releasePlayer
()
videoPresenter
.
detachView
()
}
private
fun
initView
()
{
episode_tv
.
text
=
String
.
format
(
"共%d集 %s"
,
mVedioBean
?.
vedioTotal
,
if
(
mVedioBean
?.
completeStatus
==
0
)
"已完结"
else
"更新中"
)
super_short_video_view
.
setOnCustomChildClickListener
(
this
)
fm_bottom
.
setOnClickListener
(
this
)
close_iv
.
setOnClickListener
(
this
)
}
override
fun
onClick
(
v
:
View
?)
{
if
(
AntiShake
.
check
(
v
?.
id
))
return
when
(
v
?.
id
)
{
R
.
id
.
close_iv
->
{
finish
()
}
R
.
id
.
fm_bottom
->
{
showEpisodeDialog
()
}
else
->
{}
}
}
private
fun
showEpisodeDialog
()
{
if
(
dialog
!=
null
&&
dialog
!!
.
isShowing
)
return
dialog
=
VideoEpisodeDialog
(
this
,
mVedioBean
,
object
:
DialogListener
()
{
override
fun
onClick
(
dialog
:
Dialog
?,
v
:
View
?)
{
super
.
onClick
(
dialog
,
v
)
dialog
?.
dismiss
()
}
})
dialog
?.
setCurrentIndex
(
getPosition
())
dialog
?.
setOnEpisodeClickListener
(
this
)
dialog
?.
show
()
}
override
fun
getIndexListSuc
(
indexList
:
IndexList
)
{
// 处理推荐页跳转自动播放下一集逻辑
playIndex
=
if
(
isPlayNext
)
{
mVedioBean
!!
.
recommendIndex
-
1
}
else
{
mVedioBean
!!
.
seeIndex
-
1
}
if
(
playIndex
>
mVedioBean
!!
.
vedioTotal
)
playIndex
=
0
mVedioBean
=
indexList
.
vedioMsg
indexBean
=
indexList
videos
.
clear
()
videos
.
addAll
(
indexList
.
list
)
super_short_video_view
.
loadData
(
mVedioBean
,
getAdapterData
(),
playIndex
)
}
override
fun
getIndexListFail
()
{
}
override
fun
collectSuc
()
{
mVedioBean
!!
.
collect
=
1
}
override
fun
collectFail
()
{
}
override
fun
cancelCollectSuc
()
{
mVedioBean
!!
.
collect
=
0
}
override
fun
cancelCollectFail
()
{
}
override
fun
unlockSuc
(
indexList
:
IndexList
)
{
videos
.
addAll
(
indexList
.
list
)
mVedioBean
!!
.
unlockIndex
=
videos
.
size
super_short_video_view
.
loadMoreData
(
getAdapterData
())
}
override
fun
unlockFail
()
{
}
override
fun
onEpisodeClick
(
position
:
Int
)
{
dialog
?.
dismiss
()
if
(
position
>=
mVedioBean
!!
.
unlockIndex
)
{
super_short_video_view
.
onItemClick
(
mVedioBean
!!
.
unlockIndex
)
return
}
super_short_video_view
.
onItemClick
(
position
)
Handler
(
Looper
.
getMainLooper
()).
postDelayed
({
showVipCountDialog
(
position
)
},
300
)
}
private
fun
getAdapterData
():
MutableList
<
VideoMultiItemEntity
>
{
val
data
=
mutableListOf
<
VideoMultiItemEntity
>()
if
(
videos
.
size
>
0
)
{
for
(
video
in
videos
)
{
val
item
=
VideoMultiItemEntity
(
VideoMultiItemEntity
.
MULTI_ITEM_1
,
video
)
data
.
add
(
item
)
}
if
(
mVedioBean
!!
.
unlockIndex
<
mVedioBean
!!
.
vedioTotal
)
{
val
item
=
VideoMultiItemEntity
(
VideoMultiItemEntity
.
MULTI_ITEM_2
,
videos
[
0
])
data
.
add
(
item
)
}
}
return
data
}
override
fun
onCustomChildClick
(
view
:
View
,
position
:
Int
)
{
when
(
view
.
id
)
{
R
.
id
.
ll_collect
->
{
// 收藏
mVedioBean
?.
let
{
if
(
it
.
collect
==
0
)
{
videoPresenter
.
collect
(
""
+
it
.
vedioId
)
}
else
{
videoPresenter
.
cancelCollect
(
""
+
it
.
vedioId
)
}
}
}
R
.
id
.
leave
->
{
// 返回
finish
()
}
R
.
id
.
unlock
->
{
// 看广告解锁
AdManager
.
instance
.
showAd
(
this
,
""
,
object
:
AdStatusListener
{
var
canFail
=
false
override
fun
adSuccess
()
{
canFail
=
true
}
override
fun
adFail
()
{
if
(
canFail
)
return
NoPreAdManager
.
loadVideoAd
(
this
@TxVideoActivity
,
""
,
object
:
AdStatusListener
{
override
fun
adFail
()
{
showToast
(
"广告太火爆了,请稍候再试"
)
}
override
fun
adSuccess
()
{
}
override
fun
adClose
(
vo
:
HashMap
<
String
,
Any
>?)
{
vo
?.
let
{
vo
[
"vedioId"
]
=
mVedioBean
!!
.
vedioId
videoPresenter
.
unlock
(
vo
)
}
}
})
}
override
fun
adClose
(
vo
:
HashMap
<
String
,
Any
>?)
{
vo
?.
let
{
vo
[
"vedioId"
]
=
mVedioBean
!!
.
vedioId
videoPresenter
.
unlock
(
vo
)
}
}
})
}
R
.
id
.
vip
->
{
// 开通VIP
val
bundle
=
Bundle
()
bundle
.
putString
(
VipActivity
.
VEDIO_ID
,
mVedioBean
!!
.
vedioId
.
toString
())
bundle
.
putString
(
VipActivity
.
THIRD_ID
,
mVedioBean
!!
.
thirdId
)
readyGo
(
VipActivity
::
class
.
java
,
bundle
)
}
else
->
{}
}
}
private
fun
showVipCountDialog
(
position
:
Int
)
{
if
(
isFinishing
)
return
if
(
position
==
0
||
mVedioBean
!!
.
tipMaxIndex
==
0
||
mVedioBean
!!
.
tipMaxIndex
-
1
<
position
)
{
return
}
VipCountDialog
(
this
,
mVedioBean
!!
)
.
setOnDialogDismiss
(
object
:
VipCountDialog
.
OnDialogDismiss
{
override
fun
onDialogDismiss
()
{
}
})
.
show
()
}
private
fun
getPosition
()
=
super_short_video_view
.
currentPosition
}
\ No newline at end of file
video/app/src/main/java/com/xinfu/helivideo/video/VideoBean.kt
deleted
100755 → 0
View file @
d23e5db4
package
com.xinfu.helivideo.video
import
java.io.Serializable
/**
* author : ChenWenJie
* email : 1181620038@qq.com
* date : 2020/9/22
* desc : 视频实体类
*/
class
VideoBean
:
Serializable
{
// ID
var
id
:
Int
=
0
//用户名
var
user_name
:
String
=
""
//用户头像
var
user_image
:
String
=
""
//视频标题
var
video_title
:
String
=
""
//视频路径
var
video_path
:
String
=
""
//视频图片
var
video_image
:
String
=
""
constructor
(
id
:
Int
,
user_name
:
String
,
user_image
:
String
,
video_title
:
String
,
video_path
:
String
,
video_image
:
String
)
{
this
.
id
=
id
this
.
user_name
=
user_name
this
.
user_image
=
user_image
this
.
video_title
=
video_title
this
.
video_path
=
video_path
this
.
video_image
=
video_image
}
}
\ No newline at end of file
video/app/src/main/java/com/xinfu/helivideo/video/tx/ConfigBean.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
com.tencent.rtmp.TXLiveConstants
;
import
com.tencent.rtmp.TXVodConstants
;
public
class
ConfigBean
{
private
boolean
mIsEnableSelfAdaption
;
private
boolean
mIsEnableHardWareDecode
;
private
int
mLogLevel
;
private
boolean
mIsUseDash
;
private
boolean
mEnableAccurateSeek
;
private
boolean
mSmoothSwitchBitrate
;
private
boolean
mAutoRotate
;
private
int
mConnectRetryInterval
;
private
boolean
mEnableRenderProcess
;
private
int
mProgressInterval
;
private
int
mConnectRetryCount
;
private
int
mTimeout
;
private
String
mCacheFolderPath
;
private
int
mMaxCacheItems
;
private
long
mPreferredResolution
;
private
int
mMediaType
;
private
int
mMaxPreloadSize
;
private
int
mMaxBufferSize
;
private
int
mBitRateIndex
;
private
static
volatile
ConfigBean
mInstance
;
private
ConfigBean
()
{
reset
();
}
public
static
ConfigBean
getInstance
()
{
if
(
mInstance
==
null
)
{
synchronized
(
ConfigBean
.
class
)
{
if
(
mInstance
==
null
)
{
mInstance
=
new
ConfigBean
();
}
}
}
return
mInstance
;
}
public
void
reset
()
{
setEnableAccurateSeek
(
true
);
setSmoothSwitchBitrate
(
true
);
setAutoRotate
(
true
);
setEnableSelfAdaption
(
true
);
setEnableRenderProcess
(
true
);
setConnectRetryCount
(
3
);
setConnectRetryInterval
(
3
);
setTimeout
(
10
);
setProgressInterval
(
500
);
setCacheFolderPath
(
null
);
setMaxCacheItems
(
500
);
setMaxPreloadSize
(
50
);
setMaxBufferSize
(
50
);
setPreferredResolution
(
720
*
1280
);
setMediaType
(
TXVodConstants
.
MEDIA_TYPE_AUTO
);
setEnableHardWareDecode
(
true
);
setLogLevel
(
TXLiveConstants
.
LOG_LEVEL_VERBOSE
);
}
public
boolean
isEnableSelfAdaption
()
{
return
mIsEnableSelfAdaption
;
}
public
void
setEnableSelfAdaption
(
boolean
isEnableSelfAdaption
)
{
this
.
mIsEnableSelfAdaption
=
isEnableSelfAdaption
;
}
public
boolean
isEnableHardWareDecode
()
{
return
mIsEnableHardWareDecode
;
}
public
void
setEnableHardWareDecode
(
boolean
enableHardWareDecode
)
{
this
.
mIsEnableHardWareDecode
=
enableHardWareDecode
;
}
public
int
getLogLevel
()
{
return
mLogLevel
;
}
public
void
setLogLevel
(
int
logLevel
)
{
this
.
mLogLevel
=
logLevel
;
}
public
boolean
isIsUseDash
()
{
return
mIsUseDash
;
}
public
void
setsIsUseDash
(
boolean
isUseDash
)
{
this
.
mIsUseDash
=
isUseDash
;
}
public
boolean
isEnableAccurateSeek
()
{
return
mEnableAccurateSeek
;
}
public
void
setEnableAccurateSeek
(
boolean
enableAccurateSeek
)
{
this
.
mEnableAccurateSeek
=
enableAccurateSeek
;
}
public
boolean
isSmoothSwitchBitrate
()
{
return
mSmoothSwitchBitrate
;
}
public
void
setSmoothSwitchBitrate
(
boolean
smoothSwitchBitrate
)
{
this
.
mSmoothSwitchBitrate
=
smoothSwitchBitrate
;
}
public
boolean
isAutoRotate
()
{
return
mAutoRotate
;
}
public
void
setAutoRotate
(
boolean
autoRotate
)
{
this
.
mAutoRotate
=
autoRotate
;
}
public
boolean
isEnableRenderProcess
()
{
return
mEnableRenderProcess
;
}
public
void
setEnableRenderProcess
(
boolean
enableRenderProcess
)
{
this
.
mEnableRenderProcess
=
enableRenderProcess
;
}
public
int
getProgressInterval
()
{
return
mProgressInterval
;
}
public
void
setProgressInterval
(
int
progressInterval
)
{
this
.
mProgressInterval
=
progressInterval
;
}
public
int
getConnectRetryCount
()
{
return
mConnectRetryCount
;
}
public
void
setConnectRetryCount
(
int
connectRetryCount
)
{
this
.
mConnectRetryCount
=
connectRetryCount
;
}
public
int
getTimeout
()
{
return
mTimeout
;
}
public
void
setTimeout
(
int
timeout
)
{
this
.
mTimeout
=
timeout
;
}
public
String
getCacheFolderPath
()
{
return
mCacheFolderPath
;
}
public
void
setCacheFolderPath
(
String
cacheFolderPath
)
{
this
.
mCacheFolderPath
=
cacheFolderPath
;
}
public
int
getMaxCacheItems
()
{
return
mMaxCacheItems
;
}
public
void
setMaxCacheItems
(
int
maxCacheItems
)
{
this
.
mMaxCacheItems
=
maxCacheItems
;
}
public
long
getPreferredResolution
()
{
return
mPreferredResolution
;
}
public
void
setPreferredResolution
(
long
preferredResolution
)
{
this
.
mPreferredResolution
=
preferredResolution
;
}
public
int
getMediaType
()
{
return
mMediaType
;
}
public
void
setMediaType
(
int
mediaType
)
{
this
.
mMediaType
=
mediaType
;
}
public
int
getConnectRetryInterval
()
{
return
mConnectRetryInterval
;
}
public
void
setConnectRetryInterval
(
int
connectRetryInterval
)
{
this
.
mConnectRetryInterval
=
connectRetryInterval
;
}
public
int
getMaxPreloadSize
()
{
return
mMaxPreloadSize
;
}
public
void
setMaxPreloadSize
(
int
maxPreloadSize
)
{
this
.
mMaxPreloadSize
=
maxPreloadSize
;
}
public
int
getMaxBufferSize
()
{
return
mMaxBufferSize
;
}
public
void
setMaxBufferSize
(
int
maxBufferSize
)
{
this
.
mMaxBufferSize
=
maxBufferSize
;
}
}
\ No newline at end of file
video/app/src/main/java/com/xinfu/helivideo/video/tx/PlayerManager.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
android.content.Context
;
import
android.util.Log
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
public
class
PlayerManager
{
private
static
final
String
TAG
=
"ShortVideoDemo:PlayerManager"
;
private
final
static
int
sMaxPlayerSize
=
10
;
private
Map
<
VideoModel
,
TXVodPlayerWrapper
>
mUrlPlayerMap
;
private
VideoModel
mLastPlayedVideoBean
;
private
Context
mContext
;
public
PlayerManager
(
Context
context
)
{
mContext
=
context
.
getApplicationContext
();
mUrlPlayerMap
=
new
HashMap
<>();
}
public
void
updateManager
(
List
<
VideoModel
>
shortVideoBeanList
)
{
if
(
shortVideoBeanList
==
null
||
shortVideoBeanList
.
isEmpty
())
{
return
;
}
if
(
shortVideoBeanList
.
size
()
>
sMaxPlayerSize
)
{
throw
new
IllegalArgumentException
(
"shortVideoBeanList is larger than sMaxPlayerSize"
);
}
List
<
VideoModel
>
lastBeanList
=
playedVideoModel
();
Log
.
i
(
TAG
,
" [updateManager]"
+
",urlList = "
+
shortVideoBeanList
.
toString
()
+
",lastBeanList = "
+
lastBeanList
.
toString
());
//找到 lastUrlList中不包含urlList的 lastUrlList为上次传进来的urlList urlList为这次传进来的urlList
List
<
VideoModel
>
exprList
=
findDiffBeanList
(
shortVideoBeanList
,
lastBeanList
);
//找到 urlList中不包含lastUrlList的
List
<
VideoModel
>
newList
=
findDiffBeanList
(
lastBeanList
,
shortVideoBeanList
);
if
(
exprList
!=
null
)
{
for
(
int
i
=
0
;
i
<
exprList
.
size
();
i
++)
{
Log
.
i
(
TAG
,
"[updateManager] exprUrl "
+
exprList
.
get
(
i
).
videoURL
);
}
}
if
(
newList
!=
null
)
{
for
(
int
i
=
0
;
i
<
newList
.
size
();
i
++)
{
Log
.
i
(
TAG
,
"[updateManager] newUrl "
+
newList
.
get
(
i
).
videoURL
);
}
}
if
(
newList
.
size
()
>
0
)
{
for
(
int
i
=
0
;
i
<
newList
.
size
();
i
++)
{
TXVodPlayerWrapper
tempPlayer
=
null
;
if
(
exprList
.
size
()
>
0
)
{
tempPlayer
=
mUrlPlayerMap
.
remove
(
exprList
.
remove
(
0
));
}
if
(
tempPlayer
==
null
)
{
tempPlayer
=
new
TXVodPlayerWrapper
(
mContext
);
}
tempPlayer
.
preStartPlay
(
newList
.
get
(
i
));
mUrlPlayerMap
.
put
(
newList
.
get
(
i
),
tempPlayer
);
}
}
if
(
exprList
.
size
()
>
0
)
{
for
(
int
i
=
0
;
i
<
exprList
.
size
();
i
++)
{
TXVodPlayerWrapper
exprPlayer
=
mUrlPlayerMap
.
get
(
exprList
.
get
(
i
));
mUrlPlayerMap
.
remove
(
exprList
.
get
(
i
));
exprPlayer
.
stopPlay
();
exprPlayer
=
null
;
}
}
if
(
shortVideoBeanList
.
contains
(
mLastPlayedVideoBean
))
{
Log
.
i
(
TAG
,
" [updateManager]"
+
",mLastPlayedBean = "
+
mLastPlayedVideoBean
.
videoURL
);
if
(
mUrlPlayerMap
.
get
(
mLastPlayedVideoBean
)
!=
null
)
{
mUrlPlayerMap
.
get
(
mLastPlayedVideoBean
).
preStartPlay
(
mLastPlayedVideoBean
);
}
}
}
public
TXVodPlayerWrapper
getPlayer
(
VideoModel
bean
)
{
mLastPlayedVideoBean
=
bean
;
return
mUrlPlayerMap
.
get
(
bean
);
}
private
List
<
VideoModel
>
findDiffBeanList
(
List
<
VideoModel
>
playUrlList
,
List
<
VideoModel
>
lastPlayUrlList
)
{
List
<
VideoModel
>
exprList
=
new
ArrayList
<>();
for
(
int
i
=
0
;
i
<
lastPlayUrlList
.
size
();
i
++)
{
if
(!
playUrlList
.
contains
(
lastPlayUrlList
.
get
(
i
)))
{
exprList
.
add
(
lastPlayUrlList
.
get
(
i
));
}
}
return
exprList
;
}
public
void
releasePlayer
()
{
for
(
TXVodPlayerWrapper
txVodPlayerWrapper
:
mUrlPlayerMap
.
values
())
{
txVodPlayerWrapper
.
stopPlay
();
}
mUrlPlayerMap
.
clear
();
}
private
List
<
VideoModel
>
playedVideoModel
()
{
List
<
VideoModel
>
urlList
=
new
ArrayList
<>();
for
(
VideoModel
bean
:
mUrlPlayerMap
.
keySet
())
{
urlList
.
add
(
bean
);
}
return
urlList
;
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/SuperShortVideoView.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
android.content.Context
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.widget.RelativeLayout
;
import
androidx.recyclerview.widget.LinearLayoutManager
;
import
androidx.recyclerview.widget.PagerSnapHelper
;
import
androidx.recyclerview.widget.RecyclerView
;
import
com.xinfu.helivideo.R
;
import
com.xinfu.helivideo.mvp.model.VedioBean
;
import
com.xinfu.helivideo.mvp.model.VideoMultiItemEntity
;
import
com.xinfu.helivideo.video.tx.adapter.TxVideoAdapter
;
import
java.util.ArrayList
;
import
java.util.List
;
public
class
SuperShortVideoView
extends
RelativeLayout
{
private
static
final
String
TAG
=
"SuperShortVideoView"
;
private
static
final
int
MAX_PLAYER_COUNT_ON_PASS
=
3
;
private
RecyclerView
mRecyclerView
;
private
TxVideoAdapter
mAdapter
;
private
List
<
VideoModel
>
mUrlList
;
private
LinearLayoutManager
mLayoutManager
;
private
PagerSnapHelper
mSnapHelper
;
private
int
mLastPositionInIDLE
=
-
1
;
private
TXVideoBaseView
mBaseItemView
;
private
Context
mContext
;
private
boolean
mIsOnDestroy
;
private
PlayerManager
mPlayerManager
;
private
int
mCurrentPosition
=
0
;
private
List
<
VideoMultiItemEntity
>
mList
;
public
SuperShortVideoView
(
Context
context
)
{
this
(
context
,
null
);
}
public
SuperShortVideoView
(
Context
context
,
AttributeSet
attrs
)
{
this
(
context
,
attrs
,
0
);
}
public
SuperShortVideoView
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
mContext
=
context
;
init
(
mContext
);
}
public
void
loadMoreData
(
List
<
VideoMultiItemEntity
>
list
)
{
this
.
mList
=
list
;
List
<
VideoModel
>
videoList
=
new
ArrayList
();
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
if
(
list
.
get
(
i
).
getItemType
()
==
VideoMultiItemEntity
.
MULTI_ITEM_1
)
{
videoList
.
add
(
new
VideoModel
(
list
.
get
(
i
).
getVideo
().
getVedioUrl
()));
}
}
mUrlList
.
addAll
(
videoList
);
mAdapter
.
setNewInstance
(
mList
);
onItemClick
(
mCurrentPosition
);
}
public
void
loadData
(
VedioBean
vedioBean
,
List
<
VideoMultiItemEntity
>
list
,
int
currentPosition
)
{
this
.
mList
=
list
;
this
.
mCurrentPosition
=
currentPosition
;
List
<
VideoModel
>
videoList
=
new
ArrayList
();
for
(
int
i
=
0
;
i
<
list
.
size
();
i
++)
{
if
(
list
.
get
(
i
).
getItemType
()
==
VideoMultiItemEntity
.
MULTI_ITEM_1
)
{
videoList
.
add
(
new
VideoModel
(
list
.
get
(
i
).
getVideo
().
getVedioUrl
()));
}
}
mUrlList
.
addAll
(
videoList
);
mAdapter
.
setVedioBean
(
vedioBean
);
mAdapter
.
setNewInstance
(
mList
);
onItemClick
(
mCurrentPosition
);
}
public
void
init
(
Context
context
)
{
View
mRootView
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
super_short_video_view
,
null
);
addView
(
mRootView
);
mPlayerManager
=
new
PlayerManager
(
getContext
());
mRecyclerView
=
mRootView
.
findViewById
(
R
.
id
.
rv_super_short_video
);
mUrlList
=
new
ArrayList
<>();
mSnapHelper
=
new
PagerSnapHelper
();
mSnapHelper
.
attachToRecyclerView
(
mRecyclerView
);
mAdapter
=
new
TxVideoAdapter
();
mAdapter
.
setNewInstance
(
mList
);
mAdapter
.
setOnVideoEndListener
(()
->
onItemClick
(
mCurrentPosition
+
1
));
mLayoutManager
=
new
LinearLayoutManager
(
getContext
(),
LinearLayoutManager
.
VERTICAL
,
false
)
{
@Override
protected
int
getExtraLayoutSpace
(
RecyclerView
.
State
state
)
{
return
300
;
}
};
mRecyclerView
.
setLayoutManager
(
mLayoutManager
);
mRecyclerView
.
setItemViewCacheSize
(
6
);
mRecyclerView
.
setHasFixedSize
(
true
);
mRecyclerView
.
setDrawingCacheEnabled
(
true
);
mRecyclerView
.
setDrawingCacheQuality
(
View
.
DRAWING_CACHE_QUALITY_LOW
);
mRecyclerView
.
setAdapter
(
mAdapter
);
// mLayoutManager.scrollToPosition(0);
addListener
();
}
private
void
addListener
()
{
mRecyclerView
.
addOnScrollListener
(
new
RecyclerView
.
OnScrollListener
()
{
@Override
public
void
onScrolled
(
RecyclerView
recyclerView
,
int
dx
,
int
dy
)
{
if
(!
recyclerView
.
canScrollVertically
(
1
)
||
!
recyclerView
.
canScrollVertically
(-
1
))
{
onScrollStateChanged
(
recyclerView
,
RecyclerView
.
SCROLL_STATE_IDLE
);
}
}
@Override
public
void
onScrollStateChanged
(
RecyclerView
recyclerView
,
int
newState
)
{
switch
(
newState
)
{
case
RecyclerView
.
SCROLL_STATE_IDLE
:
//停止滚动
View
view
=
mSnapHelper
.
findSnapView
(
mLayoutManager
);
int
position
=
recyclerView
.
getChildAdapterPosition
(
view
);
Log
.
i
(
TAG
,
"[SCROLL_STATE_IDLE] mLastPositionInIDLE "
+
mLastPositionInIDLE
+
" position "
+
position
);
mCurrentPosition
=
position
;
onPageSelectedMethod
(
position
);
break
;
case
RecyclerView
.
SCROLL_STATE_DRAGGING
:
//拖动
break
;
case
RecyclerView
.
SCROLL_STATE_SETTLING
:
//惯性滑动
break
;
}
}
});
}
private
void
onPageSelectedMethod
(
int
position
)
{
if
(
position
==
mUrlList
.
size
())
return
;
if
(
mLastPositionInIDLE
!=
position
)
{
View
view
=
mSnapHelper
.
findSnapView
(
mLayoutManager
);
if
(
view
==
null
)
{
return
;
}
mBaseItemView
=
view
.
findViewById
(
R
.
id
.
baseItemView
);
Log
.
i
(
TAG
,
"onPageSelected "
+
position
);
List
<
VideoModel
>
tempUrlList
=
initUrlList
(
position
,
MAX_PLAYER_COUNT_ON_PASS
);
mPlayerManager
.
updateManager
(
tempUrlList
);
TXVodPlayerWrapper
txVodPlayerWrapper
=
mPlayerManager
.
getPlayer
(
mUrlList
.
get
(
position
));
Log
.
i
(
TAG
,
"txVodPlayerWrapper "
+
txVodPlayerWrapper
+
"url-- "
+
mUrlList
.
get
(
position
).
videoURL
);
Log
.
i
(
TAG
,
"txVodPlayerWrapper "
+
txVodPlayerWrapper
);
mBaseItemView
.
setTXVodPlayer
(
txVodPlayerWrapper
);
mLastPositionInIDLE
=
position
;
}
if
(
mBaseItemView
!=
null
&&
!
mIsOnDestroy
)
{
mBaseItemView
.
startPlay
();
}
}
/**
* 初始化向PlayManager传递的urlList
*
* @param startIndex 开始的索引
* @param maxCount 传递的urlList的数目
* @return
*/
private
List
<
VideoModel
>
initUrlList
(
int
startIndex
,
int
maxCount
)
{
int
i
=
startIndex
-
1
;
if
(
i
+
maxCount
>
mUrlList
.
size
())
{
i
=
mUrlList
.
size
()
-
maxCount
;
}
if
(
i
<
0
)
{
i
=
0
;
}
int
addedCount
=
0
;
List
<
VideoModel
>
cacheList
=
new
ArrayList
<>();
while
(
i
<
mUrlList
.
size
()
&&
addedCount
<
maxCount
)
{
cacheList
.
add
(
mUrlList
.
get
(
i
));
addedCount
++;
i
++;
}
return
cacheList
;
}
public
void
resume
()
{
if
(
mBaseItemView
!=
null
)
{
mBaseItemView
.
startPlay
();
}
}
public
void
pause
()
{
if
(
mBaseItemView
!=
null
)
{
mBaseItemView
.
pausePlayer
();
}
}
public
void
releasePlayer
()
{
if
(
mBaseItemView
!=
null
)
{
mBaseItemView
.
stopPlayer
();
}
mPlayerManager
.
releasePlayer
();
}
public
void
onListPageScrolled
()
{
if
(
mBaseItemView
!=
null
)
{
mBaseItemView
.
pausePlayer
();
}
}
public
void
onItemClick
(
final
int
position
)
{
mRecyclerView
.
scrollToPosition
(
position
);
mRecyclerView
.
post
(()
->
{
Log
.
i
(
TAG
,
"onItemClick"
);
mCurrentPosition
=
position
;
onPageSelectedMethod
(
position
);
});
}
public
int
getCurrentPosition
()
{
return
mCurrentPosition
;
}
public
void
setOnCustomChildClickListener
(
TxVideoAdapter
.
OnCustomChildClickListener
onCustomChildClickListener
)
{
mAdapter
.
setOnCustomChildClickListener
(
onCustomChildClickListener
);
}
public
void
onDestroy
()
{
mIsOnDestroy
=
true
;
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/TXVideoBaseView.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
android.annotation.SuppressLint
;
import
android.content.Context
;
import
android.graphics.Color
;
import
android.os.Bundle
;
import
android.text.SpannableStringBuilder
;
import
android.text.Spanned
;
import
android.text.style.ForegroundColorSpan
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.LayoutInflater
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.widget.ImageView
;
import
android.widget.ProgressBar
;
import
android.widget.RelativeLayout
;
import
android.widget.SeekBar
;
import
android.widget.TextView
;
import
com.tencent.rtmp.TXLiveConstants
;
import
com.tencent.rtmp.ui.TXCloudVideoView
;
import
com.xinfu.helivideo.R
;
import
java.util.Locale
;
/**
* 沉浸式播放组件
*/
public
class
TXVideoBaseView
extends
RelativeLayout
implements
View
.
OnClickListener
,
SeekBar
.
OnSeekBarChangeListener
,
TXVodPlayerWrapper
.
OnPlayEventChangedListener
{
private
static
final
String
TAG
=
"TXVideoBaseView"
;
private
View
mRootView
;
private
ProgressBar
mBgProgress
;
private
SeekBar
mSeekBar
;
private
TXCloudVideoView
mTXCloudVideoView
;
private
ImageView
mIvCover
;
private
ImageView
mPauseImageView
;
private
TextView
mProgressTime
;
private
TXVodPlayerWrapper
mTXVodPlayerWrapper
;
private
boolean
mStartSeek
=
false
;
private
long
mTrackingTouchTS
=
0
;
public
TXVideoBaseView
(
Context
context
)
{
super
(
context
);
init
(
context
);
}
public
TXVideoBaseView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
init
(
context
);
}
public
TXVideoBaseView
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
init
(
context
);
}
public
void
setTXVodPlayer
(
TXVodPlayerWrapper
TXVodPlayerWrapper
)
{
mTXVodPlayerWrapper
=
TXVodPlayerWrapper
;
mTXVodPlayerWrapper
.
setPlayerView
(
mTXCloudVideoView
);
mTXCloudVideoView
.
requestLayout
();
Log
.
i
(
TAG
,
"[setTXVodPlayer] , PLAY_EVT_PLAY_PROGRESS,"
+
mTXVodPlayerWrapper
.
getVodPlayer
().
hashCode
()
+
" url "
+
TXVodPlayerWrapper
.
getUrl
());
}
@SuppressLint
(
"ClickableViewAccessibility"
)
private
void
init
(
Context
context
)
{
mRootView
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
player_item_base_view
,
null
);
addView
(
mRootView
);
mBgProgress
=
mRootView
.
findViewById
(
R
.
id
.
progress_short_video
);
mSeekBar
=
mRootView
.
findViewById
(
R
.
id
.
seekbar_short_video
);
mSeekBar
.
setOnSeekBarChangeListener
(
this
);
mIvCover
=
mRootView
.
findViewById
(
R
.
id
.
iv_cover
);
mPauseImageView
=
mRootView
.
findViewById
(
R
.
id
.
iv_pause
);
mPauseImageView
.
setOnClickListener
(
this
);
mTXCloudVideoView
=
mRootView
.
findViewById
(
R
.
id
.
tcv_video_view
);
mTXCloudVideoView
.
setOnClickListener
(
this
);
mProgressTime
=
mRootView
.
findViewById
(
R
.
id
.
tv_progress_time
);
setProgressTimeColor
(
mProgressTime
.
getText
().
toString
());
mSeekBar
.
setVisibility
(
View
.
GONE
);
mProgressTime
.
setVisibility
(
View
.
GONE
);
OnTouchListener
listener
=
new
OnTouchListener
()
{
@Override
public
boolean
onTouch
(
View
v
,
MotionEvent
event
)
{
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
mBgProgress
.
setVisibility
(
View
.
GONE
);
mSeekBar
.
setVisibility
(
View
.
VISIBLE
);
mProgressTime
.
setVisibility
(
View
.
VISIBLE
);
break
;
case
MotionEvent
.
ACTION_UP
:
mBgProgress
.
setVisibility
(
View
.
VISIBLE
);
mSeekBar
.
setVisibility
(
View
.
GONE
);
mProgressTime
.
setVisibility
(
View
.
GONE
);
break
;
}
return
false
;
}
};
mBgProgress
.
setOnTouchListener
(
listener
);
mSeekBar
.
setOnTouchListener
(
listener
);
}
private
void
handlePlayProgress
(
Bundle
param
)
{
if
(
mStartSeek
)
{
return
;
}
int
progress
=
param
.
getInt
(
TXLiveConstants
.
EVT_PLAY_PROGRESS
);
int
duration
=
param
.
getInt
(
TXLiveConstants
.
EVT_PLAY_DURATION
);
//单位为s
int
progressMS
=
param
.
getInt
(
TXLiveConstants
.
EVT_PLAY_PROGRESS_MS
);
int
durationMS
=
param
.
getInt
(
TXLiveConstants
.
EVT_PLAY_DURATION_MS
);
long
curTS
=
System
.
currentTimeMillis
();
// 避免滑动进度条松开的瞬间可能出现滑动条瞬间跳到上一个位置
if
(
Math
.
abs
(
curTS
-
mTrackingTouchTS
)
<
500
)
{
return
;
}
mTrackingTouchTS
=
curTS
;
if
(
mSeekBar
!=
null
)
{
mSeekBar
.
setMax
(
durationMS
);
mSeekBar
.
setProgress
(
progressMS
);
mBgProgress
.
setMax
(
durationMS
);
mBgProgress
.
setProgress
(
progressMS
);
}
if
(
mProgressTime
!=
null
)
{
String
tempString
=
String
.
format
(
Locale
.
CHINA
,
"%02d:%02d/%02d:%02d"
,
(
progress
)
/
60
,
progress
%
60
,
(
duration
)
/
60
,
duration
%
60
);
setProgressTimeColor
(
tempString
);
}
}
@Override
public
void
onClick
(
View
v
)
{
int
id
=
v
.
getId
();
if
(
id
==
R
.
id
.
tcv_video_view
||
id
==
R
.
id
.
iv_pause
)
{
if
(
mTXVodPlayerWrapper
==
null
)
{
return
;
}
if
(!
mTXVodPlayerWrapper
.
isPlaying
())
{
mTXVodPlayerWrapper
.
resumePlay
();
mPauseImageView
.
setVisibility
(
View
.
GONE
);
}
else
{
pausePlayer
();
}
}
}
@Override
public
void
onProgressChanged
(
SeekBar
seekBar
,
int
progress
,
boolean
fromUser
)
{
if
(
mProgressTime
!=
null
)
{
String
tempString
=
String
.
format
(
Locale
.
CHINA
,
"%02d:%02d/%02d:%02d"
,
(
progress
/
1000
)
/
60
,
(
progress
/
1000
)
%
60
,
(
seekBar
.
getMax
()
/
1000
)
/
60
,
(
seekBar
.
getMax
()
/
1000
)
%
60
);
setProgressTimeColor
(
tempString
);
}
}
private
void
setProgressTimeColor
(
String
value
)
{
SpannableStringBuilder
builder
=
new
SpannableStringBuilder
(
value
);
ForegroundColorSpan
gray
=
new
ForegroundColorSpan
(
Color
.
GRAY
);
ForegroundColorSpan
white
=
new
ForegroundColorSpan
(
Color
.
WHITE
);
builder
.
setSpan
(
gray
,
5
,
11
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
builder
.
setSpan
(
white
,
0
,
5
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
mProgressTime
.
setText
(
builder
);
}
@Override
public
void
onStartTrackingTouch
(
SeekBar
seekBar
)
{
mStartSeek
=
true
;
// 解决viewPager和的滑动冲突问题
getParent
().
requestDisallowInterceptTouchEvent
(
true
);
}
@Override
public
void
onStopTrackingTouch
(
SeekBar
seekBar
)
{
// 解决viewPager和的滑动冲突问题
getParent
().
requestDisallowInterceptTouchEvent
(
false
);
if
(
mTXVodPlayerWrapper
!=
null
)
{
Log
.
i
(
TAG
,
"[onStopTrackingTouch] seekBar.getProgress() "
+
seekBar
.
getProgress
());
mTXVodPlayerWrapper
.
seekTo
(
seekBar
.
getProgress
()
/
1000
F
);
}
mTrackingTouchTS
=
System
.
currentTimeMillis
();
mStartSeek
=
false
;
}
public
void
pausePlayer
()
{
if
(
mTXVodPlayerWrapper
!=
null
)
{
mTXVodPlayerWrapper
.
pausePlay
();
mPauseImageView
.
setVisibility
(
View
.
VISIBLE
);
}
}
public
void
startPlay
()
{
if
(
mTXVodPlayerWrapper
!=
null
)
{
mPauseImageView
.
setVisibility
(
View
.
GONE
);
mTXVodPlayerWrapper
.
setVodChangeListener
(
this
);
mTXVodPlayerWrapper
.
resumePlay
();
Log
.
i
(
TAG
,
"[startPlay] mTXVodPlayerWrapper.url "
+
mTXVodPlayerWrapper
.
getUrl
());
}
}
public
void
stopPlayer
()
{
if
(
mTXVodPlayerWrapper
!=
null
)
{
mTXVodPlayerWrapper
.
stopPlay
();
mTXVodPlayerWrapper
.
setVodChangeListener
(
null
);
Log
.
i
(
TAG
,
"[stopPlayer] mTXVodPlayerWrapper.url "
+
mTXVodPlayerWrapper
.
getUrl
());
mPauseImageView
.
setVisibility
(
View
.
GONE
);
}
}
public
void
stopForPlaying
()
{
if
(
mTXVodPlayerWrapper
!=
null
)
{
mTXVodPlayerWrapper
.
stopForPlaying
();
mTXVodPlayerWrapper
.
setVodChangeListener
(
null
);
Log
.
i
(
TAG
,
"[stopForPlaying] mTXVodPlayerWrapper.url "
+
mTXVodPlayerWrapper
.
getUrl
());
mPauseImageView
.
setVisibility
(
View
.
GONE
);
mIvCover
.
setVisibility
(
VISIBLE
);
}
}
@Override
public
void
onProgress
(
Bundle
bundle
)
{
handlePlayProgress
(
bundle
);
}
@Override
public
void
onRcvFirstFrame
()
{
Log
.
i
(
TAG
,
"[onPrepared in TXVideoBaseView]"
);
mIvCover
.
setVisibility
(
GONE
);
}
@Override
public
void
onEnded
()
{
if
(
this
.
mOnVideoEndListener
!=
null
)
{
this
.
mOnVideoEndListener
.
onVideoEnd
();
}
}
public
void
setOnVideoEndListener
(
OnVideoEndListener
onVideoEndListener
)
{
this
.
mOnVideoEndListener
=
onVideoEndListener
;
}
private
OnVideoEndListener
mOnVideoEndListener
;
public
interface
OnVideoEndListener
{
void
onVideoEnd
();
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/TXVodPlayerWrapper.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
static
com
.
tencent
.
rtmp
.
TXLiveConstants
.
PLAY_EVT_PLAY_END
;
import
static
com
.
tencent
.
rtmp
.
TXLiveConstants
.
PLAY_EVT_PLAY_PROGRESS
;
import
static
com
.
tencent
.
rtmp
.
TXLiveConstants
.
PLAY_EVT_RCV_FIRST_I_FRAME
;
import
static
com
.
tencent
.
rtmp
.
TXLiveConstants
.
PLAY_EVT_VOD_PLAY_PREPARED
;
import
android.content.Context
;
import
android.os.Bundle
;
import
android.util.Log
;
import
com.tencent.rtmp.ITXVodPlayListener
;
import
com.tencent.rtmp.TXPlayerGlobalSetting
;
import
com.tencent.rtmp.TXVodConstants
;
import
com.tencent.rtmp.TXVodPlayConfig
;
import
com.tencent.rtmp.TXVodPlayer
;
import
com.tencent.rtmp.ui.TXCloudVideoView
;
import
java.io.File
;
public
class
TXVodPlayerWrapper
implements
ITXVodPlayListener
{
private
static
final
String
TAG
=
"ShortVideoDemo:TXVodPlayerWrapper"
;
private
TXVodPlayer
mVodPlayer
;
private
OnPlayEventChangedListener
mOnPlayEventChangedListener
;
private
TxVodStatus
mStatus
;
private
String
mUrl
;
private
boolean
mStartOnPrepare
;
private
TXVodPlayConfig
mTXVodPlayConfig
;
public
TXVodPlayerWrapper
(
Context
context
)
{
mVodPlayer
=
new
TXVodPlayer
(
context
);
mVodPlayer
.
setVodListener
(
this
);
if
(
ConfigBean
.
getInstance
().
isIsUseDash
())
{
mVodPlayer
.
setRenderMode
(
TXVodConstants
.
RENDER_MODE_ADJUST_RESOLUTION
);
}
else
{
mVodPlayer
.
setRenderMode
(
TXVodConstants
.
RENDER_MODE_FULL_FILL_SCREEN
);
}
mTXVodPlayConfig
=
new
TXVodPlayConfig
();
mTXVodPlayConfig
.
setProgressInterval
(
500
);
mTXVodPlayConfig
.
setSmoothSwitchBitrate
(
true
);
mTXVodPlayConfig
.
setMaxBufferSize
(
5
);
mTXVodPlayConfig
.
setPreferredResolution
(
1080
*
1920
);
mTXVodPlayConfig
.
setMaxCacheItems
(
8
);
if
(
TXPlayerGlobalSetting
.
getCacheFolderPath
()
==
null
||
TXPlayerGlobalSetting
.
getCacheFolderPath
().
equals
(
""
))
{
File
sdcardDir
=
context
.
getExternalFilesDir
(
null
);
TXPlayerGlobalSetting
.
setCacheFolderPath
(
sdcardDir
.
getPath
()
+
"/txcache"
);
}
mVodPlayer
.
setConfig
(
mTXVodPlayConfig
);
}
@Override
public
void
onPlayEvent
(
TXVodPlayer
txVodPlayer
,
int
event
,
Bundle
bundle
)
{
switch
(
event
)
{
case
PLAY_EVT_VOD_PLAY_PREPARED:
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PREPARED
);
Log
.
i
(
TAG
,
"[onPlayEvent] , startOnPrepare,"
+
mStartOnPrepare
+
",mVodPlayer "
+
mVodPlayer
.
hashCode
()
+
" mUrl "
+
mUrl
);
if
(
mStartOnPrepare
)
{
mVodPlayer
.
resume
();
mStartOnPrepare
=
false
;
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PLAYING
);
}
break
;
case
PLAY_EVT_RCV_FIRST_I_FRAME:
if
(
mOnPlayEventChangedListener
!=
null
)
{
mOnPlayEventChangedListener
.
onRcvFirstFrame
();
}
break
;
case
PLAY_EVT_PLAY_PROGRESS:
if
(
mOnPlayEventChangedListener
!=
null
)
{
mOnPlayEventChangedListener
.
onProgress
(
bundle
);
}
break
;
case
PLAY_EVT_PLAY_END:
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_ENDED
);
if
(
mOnPlayEventChangedListener
!=
null
)
{
mOnPlayEventChangedListener
.
onEnded
();
}
break
;
default
:
break
;
}
}
@Override
public
void
onNetStatus
(
TXVodPlayer
txVodPlayer
,
Bundle
bundle
)
{
}
public
void
pausePlay
()
{
mVodPlayer
.
pause
();
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PAUSED
);
}
public
void
resumePlay
()
{
Log
.
i
(
TAG
,
"[resumePlay] , startOnPrepare, "
+
mStartOnPrepare
+
" mVodPlayer "
+
mVodPlayer
.
hashCode
()
+
" url "
+
mUrl
);
if
(
mStatus
==
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_STOPPED
)
{
mVodPlayer
.
setAutoPlay
(
true
);
mVodPlayer
.
startVodPlay
(
mUrl
);
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PLAYING
);
return
;
}
if
(
mStatus
==
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PREPARED
||
mStatus
==
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PAUSED
)
{
mVodPlayer
.
resume
();
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PLAYING
);
}
else
{
mStartOnPrepare
=
true
;
}
}
public
void
seekTo
(
float
time
)
{
mVodPlayer
.
seek
(
time
);
}
public
boolean
isPlaying
()
{
return
mVodPlayer
.
isPlaying
();
}
public
void
stopForPlaying
()
{
if
(
mStatus
==
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_PLAYING
)
{
mVodPlayer
.
stopPlay
(
true
);
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_STOPPED
);
}
}
public
void
stopPlay
()
{
mVodPlayer
.
stopPlay
(
true
);
playerStatusChanged
(
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_STOPPED
);
}
public
void
setPlayerView
(
TXCloudVideoView
txCloudVideoView
)
{
mVodPlayer
.
setPlayerView
(
txCloudVideoView
);
}
public
void
preStartPlay
(
VideoModel
bean
)
{
this
.
mUrl
=
bean
.
videoURL
;
this
.
mStatus
=
TxVodStatus
.
TX_VIDEO_PLAYER_STATUS_UNLOAD
;
mStartOnPrepare
=
false
;
mVodPlayer
.
setLoop
(
false
);
mVodPlayer
.
stopPlay
(
true
);
Log
.
i
(
TAG
,
"[preStartPlay] , startOnPrepare ,"
+
mStartOnPrepare
+
", mVodPlayer "
+
mVodPlayer
.
hashCode
());
mVodPlayer
.
setAutoPlay
(
false
);
mVodPlayer
.
startVodPlay
(
bean
.
videoURL
);
}
private
void
playerStatusChanged
(
TxVodStatus
status
)
{
this
.
mStatus
=
status
;
Log
.
i
(
TAG
,
" [playerStatusChanged] mVodPlayer"
+
mVodPlayer
.
hashCode
()
+
" mStatus "
+
mStatus
);
}
public
void
setVodChangeListener
(
OnPlayEventChangedListener
listener
)
{
mOnPlayEventChangedListener
=
listener
;
}
public
enum
TxVodStatus
{
TX_VIDEO_PLAYER_STATUS_UNLOAD
,
// 未加载
TX_VIDEO_PLAYER_STATUS_PREPARED
,
// 准备播放
TX_VIDEO_PLAYER_STATUS_LOADING
,
// 加载中
TX_VIDEO_PLAYER_STATUS_PLAYING
,
// 播放中
TX_VIDEO_PLAYER_STATUS_PAUSED
,
// 暂停
TX_VIDEO_PLAYER_STATUS_ENDED
,
// 播放完成
TX_VIDEO_PLAYER_STATUS_STOPPED
// 手动停止播放
}
public
interface
OnPlayEventChangedListener
{
void
onProgress
(
Bundle
bundle
);
void
onRcvFirstFrame
();
void
onEnded
();
}
public
TXVodPlayer
getVodPlayer
()
{
return
mVodPlayer
;
}
public
String
getUrl
()
{
return
mUrl
;
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/VideoModel.java
0 → 100755
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
;
import
java.io.Serializable
;
/**
* Created by yuejiaoli on 2018/7/4.
*/
public
class
VideoModel
implements
Serializable
{
public
VideoModel
(
String
videoURL
)
{
this
.
videoURL
=
videoURL
;
}
/**
* 视频URL
*/
public
String
videoURL
;
/**
* 从服务器拉取的封面图片
*/
public
String
placeholderImage
;
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/adapter/AbsPlayerRecyclerViewAdapter.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
.
adapter
;
import
android.content.Context
;
import
android.view.LayoutInflater
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
androidx.recyclerview.widget.RecyclerView
;
import
java.util.List
;
public
abstract
class
AbsPlayerRecyclerViewAdapter
<
T
,
K
extends
AbsViewHolder
>
extends
RecyclerView
.
Adapter
<
K
>
{
private
List
<
T
>
mList
;
public
Context
mContext
;
public
AbsPlayerRecyclerViewAdapter
(
List
<
T
>
list
)
{
this
.
mList
=
list
;
}
@Override
public
K
onCreateViewHolder
(
ViewGroup
parent
,
int
viewType
)
{
mContext
=
parent
.
getContext
();
K
holder
=
onCreateHolder
(
parent
);
return
holder
;
}
@Override
public
void
onBindViewHolder
(
K
holder
,
int
position
)
{
onHolder
(
holder
,
mList
.
get
(
position
),
position
);
}
@Override
public
int
getItemViewType
(
int
position
)
{
return
position
;
}
@Override
public
int
getItemCount
()
{
return
mList
==
null
?
0
:
mList
.
size
();
}
public
abstract
void
onHolder
(
K
holder
,
T
bean
,
int
position
);
public
abstract
K
onCreateHolder
(
ViewGroup
parent
);
public
View
getViewByRes
(
int
res
,
ViewGroup
parent
)
{
return
LayoutInflater
.
from
(
mContext
).
inflate
(
res
,
parent
,
false
);
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/adapter/AbsViewHolder.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
.
adapter
;
import
android.view.View
;
import
androidx.recyclerview.widget.RecyclerView
;
public
abstract
class
AbsViewHolder
extends
RecyclerView
.
ViewHolder
{
public
AbsViewHolder
(
View
itemView
)
{
super
(
itemView
);
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/adapter/ShortVideoPlayAdapter.java
0 → 100644
View file @
fa2428dd
package
com
.
xinfu
.
helivideo
.
video
.
tx
.
adapter
;
import
android.content.Context
;
import
android.util.Log
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
androidx.annotation.NonNull
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.engine.DiskCacheStrategy
;
import
com.tencent.rtmp.ui.TXCloudVideoView
;
import
com.xinfu.helivideo.R
;
import
com.xinfu.helivideo.video.tx.TXVideoBaseView
;
import
com.xinfu.helivideo.video.tx.VideoModel
;
import
java.util.List
;
public
class
ShortVideoPlayAdapter
extends
AbsPlayerRecyclerViewAdapter
<
VideoModel
,
ShortVideoPlayAdapter
.
VideoViewHolder
>
{
private
static
final
String
TAG
=
"ShortVideoDemo:ShortVideoPlayAdapter"
;
private
Context
mContext
;
public
ShortVideoPlayAdapter
(
Context
context
,
List
<
VideoModel
>
list
)
{
super
(
list
);
mContext
=
context
;
}
@Override
public
void
onHolder
(
VideoViewHolder
holder
,
VideoModel
bean
,
int
position
)
{
if
(
bean
!=
null
&&
bean
.
placeholderImage
!=
null
)
{
Glide
.
with
(
mContext
).
load
(
bean
.
placeholderImage
)
.
skipMemoryCache
(
true
)
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
).
centerCrop
()
.
into
(
holder
.
mImageViewCover
);
}
}
@Override
public
void
onViewRecycled
(
@NonNull
VideoViewHolder
holder
)
{
super
.
onViewRecycled
(
holder
);
Glide
.
with
(
mContext
).
clear
(
holder
.
mImageViewCover
);
}
@Override
public
VideoViewHolder
onCreateHolder
(
ViewGroup
viewGroup
)
{
return
new
VideoViewHolder
(
getViewByRes
(
R
.
layout
.
player_item_short_video_play
,
viewGroup
));
}
@Override
public
void
onViewDetachedFromWindow
(
@NonNull
VideoViewHolder
holder
)
{
super
.
onViewDetachedFromWindow
(
holder
);
Log
.
i
(
TAG
,
"onViewDetachedFromWindow"
);
TXVideoBaseView
videoView
=
(
TXVideoBaseView
)
holder
.
mRootView
.
findViewById
(
R
.
id
.
baseItemView
);
videoView
.
stopForPlaying
();
}
public
class
VideoViewHolder
extends
AbsViewHolder
{
public
View
mRootView
;
public
TextView
mEpisodeTv
;
public
ImageView
mImageViewCover
;
public
TXCloudVideoView
mVideoView
;
public
VideoViewHolder
(
View
rootView
)
{
super
(
rootView
);
this
.
mRootView
=
rootView
;
this
.
mImageViewCover
=
rootView
.
findViewById
(
R
.
id
.
iv_cover
);
this
.
mVideoView
=
rootView
.
findViewById
(
R
.
id
.
tcv_video_view
);
}
}
}
video/app/src/main/java/com/xinfu/helivideo/video/tx/adapter/TxVideoAdapter.kt
0 → 100755
View file @
fa2428dd
package
com.xinfu.helivideo.video.tx.adapter
import
android.view.View
import
android.widget.LinearLayout
import
android.widget.TextView
import
com.airbnb.lottie.LottieAnimationView
import
com.airbnb.lottie.LottieComposition
import
com.airbnb.lottie.LottieCompositionFactory
import
com.airbnb.lottie.LottieDrawable
import
com.bumptech.glide.Glide
import
com.bumptech.glide.load.engine.DiskCacheStrategy
import
com.chad.library.adapter.base.BaseMultiItemQuickAdapter
import
com.chad.library.adapter.base.viewholder.BaseViewHolder
import
com.xinfu.helivideo.R
import
com.xinfu.helivideo.mvp.model.VedioBean
import
com.xinfu.helivideo.mvp.model.VideoMultiItemEntity
import
com.xinfu.helivideo.video.tx.TXVideoBaseView
class
TxVideoAdapter
:
BaseMultiItemQuickAdapter
<
VideoMultiItemEntity
,
BaseViewHolder
>()
{
private
var
vedioBean
:
VedioBean
?
=
null
init
{
addItemType
(
VideoMultiItemEntity
.
MULTI_ITEM_1
,
R
.
layout
.
player_item_short_video_play
)
addItemType
(
VideoMultiItemEntity
.
MULTI_ITEM_2
,
R
.
layout
.
item_block_view
)
}
override
fun
convert
(
holder
:
BaseViewHolder
,
item
:
VideoMultiItemEntity
)
{
if
(
holder
.
itemViewType
==
VideoMultiItemEntity
.
MULTI_ITEM_1
)
{
initVideoHolder
(
holder
,
item
)
}
else
{
initLockHolder
(
holder
)
}
}
private
fun
initLockHolder
(
holder
:
BaseViewHolder
)
{
Glide
.
with
(
context
).
load
(
vedioBean
?.
coverImage
)
.
into
(
holder
.
getView
(
R
.
id
.
iv_bg
))
holder
.
getView
<
View
>(
R
.
id
.
vip
).
setOnClickListener
{
mOnCustomChildClickListener
?.
onCustomChildClick
(
it
,
holder
.
adapterPosition
)
}
holder
.
getView
<
TextView
>(
R
.
id
.
unlock
).
text
=
"看广告解锁"
+
vedioBean
?.
adGiveVedioNum
+
"集"
holder
.
getView
<
View
>(
R
.
id
.
unlock
).
setOnClickListener
{
mOnCustomChildClickListener
?.
onCustomChildClick
(
it
,
holder
.
adapterPosition
)
}
}
private
fun
initVideoHolder
(
holder
:
BaseViewHolder
,
item
:
VideoMultiItemEntity
)
{
//标题
holder
.
setText
(
R
.
id
.
title_tv
,
vedioBean
?.
title
)
//集数
holder
.
setText
(
R
.
id
.
info_tv
,
"第"
+
item
.
video
.
vedioIndex
+
"集"
)
//收藏数量
holder
.
setText
(
R
.
id
.
zan_num_tv
,
""
+
vedioBean
?.
hot
)
//缩略图
Glide
.
with
(
context
).
load
(
vedioBean
?.
coverImage
)
.
skipMemoryCache
(
true
)
.
diskCacheStrategy
(
DiskCacheStrategy
.
ALL
).
centerCrop
()
.
into
(
holder
.
getView
<
TXVideoBaseView
>(
R
.
id
.
baseItemView
).
findViewById
(
R
.
id
.
iv_cover
))
holder
.
getView
<
LinearLayout
>(
R
.
id
.
ll_collect
).
setOnClickListener
{
mOnCustomChildClickListener
?.
onCustomChildClick
(
it
,
holder
.
adapterPosition
)
if
(
vedioBean
?.
collect
==
0
)
{
playCollectAnim
(
holder
.
getView
(
R
.
id
.
zan_iv
))
}
else
{
playCancelCollectAnim
(
holder
.
getView
(
R
.
id
.
zan_iv
))
}
}
if
(
vedioBean
?.
collect
==
0
)
{
// 未收藏
setCollectImage
(
holder
.
getView
(
R
.
id
.
zan_iv
))
}
else
{
// 已收藏
setCancelCollectImage
(
holder
.
getView
(
R
.
id
.
zan_iv
))
}
holder
.
getView
<
TXVideoBaseView
>(
R
.
id
.
baseItemView
).
setOnVideoEndListener
(
mOnVideoEndListener
)
}
override
fun
onViewDetachedFromWindow
(
holder
:
BaseViewHolder
)
{
super
.
onViewDetachedFromWindow
(
holder
)
if
(
holder
.
itemViewType
==
VideoMultiItemEntity
.
MULTI_ITEM_1
)
{
holder
.
getView
<
TXVideoBaseView
>(
R
.
id
.
baseItemView
).
stopForPlaying
()
}
}
override
fun
onViewRecycled
(
holder
:
BaseViewHolder
)
{
super
.
onViewRecycled
(
holder
)
if
(
holder
.
itemViewType
==
VideoMultiItemEntity
.
MULTI_ITEM_1
)
{
Glide
.
with
(
context
).
clear
(
holder
.
getView
<
View
>(
R
.
id
.
iv_cover
))
}
}
private
fun
setCollectImage
(
view
:
LottieAnimationView
)
{
val
lottieDrawable
=
LottieDrawable
()
LottieCompositionFactory
.
fromAsset
(
context
,
"home_collect.json"
)
.
addListener
{
result
:
LottieComposition
?
->
lottieDrawable
.
setImagesAssetsFolder
(
"images/"
)
lottieDrawable
.
composition
=
result
}
view
.
setImageDrawable
(
lottieDrawable
)
}
private
fun
setCancelCollectImage
(
view
:
LottieAnimationView
)
{
val
lottieDrawable
=
LottieDrawable
()
LottieCompositionFactory
.
fromAsset
(
context
,
"home_cancel_collect.json"
)
.
addListener
{
result
:
LottieComposition
?
->
lottieDrawable
.
setImagesAssetsFolder
(
"images/"
)
lottieDrawable
.
composition
=
result
}
view
.
setImageDrawable
(
lottieDrawable
)
}
private
fun
playCollectAnim
(
view
:
LottieAnimationView
)
{
val
lottieDrawable
=
LottieDrawable
()
LottieCompositionFactory
.
fromAsset
(
context
,
"home_collect.json"
)
.
addListener
{
result
:
LottieComposition
?
->
lottieDrawable
.
setImagesAssetsFolder
(
"images/"
)
lottieDrawable
.
composition
=
result
lottieDrawable
.
loop
(
false
)
lottieDrawable
.
playAnimation
()
}
view
.
setImageDrawable
(
lottieDrawable
)
}
private
fun
playCancelCollectAnim
(
view
:
LottieAnimationView
)
{
val
lottieDrawable
=
LottieDrawable
()
LottieCompositionFactory
.
fromAsset
(
context
,
"home_cancel_collect.json"
)
.
addListener
{
result
:
LottieComposition
?
->
lottieDrawable
.
setImagesAssetsFolder
(
"images/"
)
lottieDrawable
.
composition
=
result
lottieDrawable
.
loop
(
false
)
lottieDrawable
.
playAnimation
()
}
view
.
setImageDrawable
(
lottieDrawable
)
}
private
var
mOnVideoEndListener
:
TXVideoBaseView
.
OnVideoEndListener
?
=
null
fun
setOnVideoEndListener
(
onVideoEndListener
:
TXVideoBaseView
.
OnVideoEndListener
)
{
this
.
mOnVideoEndListener
=
onVideoEndListener
}
private
var
mOnCustomChildClickListener
:
OnCustomChildClickListener
?
=
null
fun
setOnCustomChildClickListener
(
onCustomChildClickListener
:
OnCustomChildClickListener
)
{
this
.
mOnCustomChildClickListener
=
onCustomChildClickListener
}
interface
OnCustomChildClickListener
{
fun
onCustomChildClick
(
view
:
View
,
position
:
Int
)
}
fun
setVedioBean
(
vedioBean
:
VedioBean
)
{
this
.
vedioBean
=
vedioBean
}
}
\ No newline at end of file
video/app/src/main/res/drawable/player_short_video_time.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<stroke
android:width=
"1dp"
android:color=
"@color/white"
></stroke>
<corners
android:radius=
"20dp"
></corners>
<solid
android:color=
"#4D000000"
/>
</shape>
\ No newline at end of file
video/app/src/main/res/drawable/player_thumb_view.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item
android:state_pressed=
"true"
>
<shape
android:shape=
"oval"
>
<solid
android:color=
"#FFFFFFFF"
/>
<size
android:width=
"8dp"
android:height=
"8dp"
/>
</shape>
</item>
<item>
<shape
android:shape=
"oval"
>
<solid
android:color=
"#FFFFFFFF"
/>
<size
android:width=
"8dp"
android:height=
"8dp"
/>
</shape>
</item>
</selector>
\ No newline at end of file
video/app/src/main/res/drawable/player_video_seek_bar.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item
android:id=
"@android:id/background"
android:height=
"5dp"
>
<shape>
<corners
android:radius=
"5dp"
/>
<solid
android:color=
"#4CD8D8D8"
/>
<!-- 颜色-->
</shape>
</item>
<item
android:id=
"@android:id/secondaryProgress"
android:height=
"5dp"
>
<clip>
<shape>
<corners
android:radius=
"5dp"
/>
<solid
android:color=
"#20B2AA"
/>
<!-- 颜色-->
</shape>
</clip>
</item>
<item
android:id=
"@android:id/progress"
android:height=
"5dp"
>
<clip>
<shape>
<corners
android:radius=
"5dp"
/>
<solid
android:color=
"#C9C7C7"
/>
<!-- 颜色-->
</shape>
</clip>
</item>
</layer-list>
\ No newline at end of file
video/app/src/main/res/layout/activity_tx_video.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/black"
android:orientation=
"vertical"
>
<com.xinfu.helivideo.video.tx.SuperShortVideoView
android:id=
"@+id/super_short_video_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
<ImageView
android:id=
"@+id/close_iv"
android:layout_width=
"50dp"
android:layout_height=
"50dp"
android:layout_marginTop=
"20dp"
android:padding=
"10dp"
android:src=
"@mipmap/ic_arrow_white"
/>
<FrameLayout
android:id=
"@+id/fm_bottom"
android:layout_width=
"match_parent"
android:layout_height=
"50dp"
android:layout_gravity=
"bottom"
>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"@dimen/dp_40"
android:layout_gravity=
"center"
android:layout_marginStart=
"20dp"
android:layout_marginEnd=
"20dp"
android:background=
"@drawable/shape_half_trans"
android:gravity=
"center_vertical"
android:orientation=
"horizontal"
android:paddingStart=
"@dimen/dp_10"
android:paddingEnd=
"@dimen/dp_10"
>
<ImageView
android:layout_width=
"20dp"
android:layout_height=
"20dp"
android:src=
"@mipmap/ic_video_epsiode"
/>
<TextView
android:id=
"@+id/episode_tv"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"10dp"
android:layout_weight=
"1"
android:text=
"共100集 已完结"
android:textColor=
"@color/white"
/>
<ImageView
android:layout_width=
"20dp"
android:layout_height=
"20dp"
android:src=
"@mipmap/ic_arrow_top"
/>
</LinearLayout>
</FrameLayout>
</FrameLayout>
\ No newline at end of file
video/app/src/main/res/layout/item_block_view.xml
View file @
fa2428dd
...
...
@@ -49,14 +49,4 @@
</LinearLayout>
</FrameLayout>
<ImageView
android:id=
"@+id/leave"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"20dp"
android:padding=
"10dp"
android:src=
"@mipmap/ic_arrow_white"
/>
</FrameLayout>
video/app/src/main/res/layout/item_video.xml
View file @
fa2428dd
...
...
@@ -20,50 +20,47 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"15dp"
android:
orientation=
"horizontal
"
android:
layout_marginBottom=
"10dp
"
app:layout_constraintBottom_to
TopOf=
"@id/info_tv
"
android:
layout_marginBottom=
"100dp
"
android:
orientation=
"vertical
"
app:layout_constraintBottom_to
BottomOf=
"parent
"
app:layout_constraintLeft_toLeftOf=
"parent"
>
<TextView
android:id=
"@+id/title_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"
match_par
ent"
android:layout_height=
"
wrap_cont
ent"
android:ellipsize=
"end"
android:gravity=
"center"
android:maxEms=
"9"
android:maxLines=
"1"
android:textStyle=
"bold"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"16sp"
/>
</LinearLayout
>
android:textSize=
"16sp"
android:textStyle=
"bold"
/
>
<TextView
android:id=
"@+id/info_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginBottom=
"24dp"
android:layout_marginStart=
"15dp"
android:ellipsize=
"end"
android:gravity=
"center|left"
android:maxEms=
"14"
android:maxLines=
"3"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"14sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
tools:ignore=
"RtlHardcoded"
/>
<TextView
android:id=
"@+id/info_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:gravity=
"center|left"
android:maxEms=
"14"
android:maxLines=
"3"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"14sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
/>
</LinearLayout>
<LinearLayout
android:id=
"@+id/ll_collect"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"15dp"
android:layout_marginBottom=
"40dp"
android:gravity=
"center"
android:orientation=
"vertical"
android:layout_marginBottom=
"40dp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
>
...
...
@@ -78,8 +75,8 @@
android:id=
"@+id/zan_num_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:gravity=
"center"
android:layout_marginTop=
"6dp"
android:gravity=
"center"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"14sp"
/>
...
...
video/app/src/main/res/layout/player_item_base_view.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<com.tencent.rtmp.ui.TXCloudVideoView
android:id=
"@+id/tcv_video_view"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
/>
<View
android:id=
"@+id/empty_view"
android:layout_width=
"match_parent"
android:layout_height=
"52dp"
android:layout_alignParentBottom=
"true"
android:background=
"@android:color/transparent"
/>
<ImageView
android:id=
"@+id/iv_cover"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:layout_gravity=
"center"
android:scaleType=
"centerInside"
android:visibility=
"visible"
/>
<SeekBar
android:id=
"@+id/seekbar_short_video"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_above=
"@id/empty_view"
android:maxHeight=
"6dp"
android:minHeight=
"6dp"
android:progressDrawable=
"@drawable/player_video_seek_bar"
android:thumb=
"@drawable/player_thumb_view"
/>
<TextView
android:id=
"@+id/tv_progress_time"
android:layout_width=
"118dp"
android:layout_height=
"30dp"
android:layout_above=
"@id/seekbar_short_video"
android:layout_centerHorizontal=
"true"
android:layout_marginBottom=
"12dp"
android:background=
"@drawable/player_short_video_time"
android:gravity=
"center"
android:text=
"00:00/00:00"
android:textSize=
"16sp"
/>
<ProgressBar
android:id=
"@+id/progress_short_video"
style=
"?android:attr/progressBarStyleHorizontal"
android:layout_width=
"match_parent"
android:layout_height=
"6dp"
android:layout_above=
"@id/empty_view"
android:max=
"100"
android:progressDrawable=
"@drawable/jz_bottom_seek_progress"
/>
<ImageView
android:id=
"@+id/iv_pause"
android:layout_width=
"80dp"
android:layout_height=
"80dp"
android:layout_centerHorizontal=
"true"
android:layout_marginTop=
"314dp"
android:src=
"@mipmap/player_pause"
android:visibility=
"gone"
/>
</RelativeLayout>
video/app/src/main/res/layout/player_item_short_video_play.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<com.xinfu.helivideo.video.tx.TXVideoBaseView
android:id=
"@+id/baseItemView"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
<LinearLayout
android:id=
"@+id/ll"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"15dp"
android:layout_marginBottom=
"120dp"
android:orientation=
"vertical"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
>
<TextView
android:id=
"@+id/title_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:gravity=
"center"
android:maxEms=
"9"
android:maxLines=
"1"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"16sp"
android:textStyle=
"bold"
/>
<TextView
android:id=
"@+id/info_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:ellipsize=
"end"
android:gravity=
"center|left"
android:maxEms=
"14"
android:maxLines=
"3"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"14sp"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintLeft_toLeftOf=
"parent"
/>
</LinearLayout>
<LinearLayout
android:id=
"@+id/ll_collect"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginEnd=
"15dp"
android:layout_marginBottom=
"160dp"
android:gravity=
"center"
android:orientation=
"vertical"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintRight_toRightOf=
"parent"
>
<com.airbnb.lottie.LottieAnimationView
android:id=
"@+id/zan_iv"
android:layout_width=
"35dp"
android:layout_height=
"35dp"
android:layout_marginTop=
"10dp"
android:src=
"@mipmap/home_collect_img_0"
/>
<TextView
android:id=
"@+id/zan_num_tv"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:gravity=
"center"
android:text=
"-"
android:textColor=
"#fff"
android:textSize=
"14sp"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
video/app/src/main/res/layout/super_short_video_view.xml
0 → 100644
View file @
fa2428dd
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
>
<androidx.recyclerview.widget.RecyclerView
android:id=
"@+id/rv_super_short_video"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
</RelativeLayout>
\ No newline at end of file
video/app/src/main/res/mipmap-xhdpi/player_pause.png
0 → 100644
View file @
fa2428dd
9.68 KB
video/settings.gradle
View file @
fa2428dd
...
...
@@ -3,4 +3,4 @@ include ':oaid'
include
':rxpay'
include
':alipay'
include
':wxpay'
include
':videocache'
\ No newline at end of file
include
':videocache'
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment