@@ -241,6 +241,9 @@ | |||
<entry key="..\:/xuekaole/XKLLocal/app/src/main/res/layout/fragment_statistics_time_top.xml" value="0.23385416666666667" /> | |||
<entry key="..\:/xuekaole/XKLLocal/app/src/main/res/layout/item_statics_for_time.xml" value="0.24791666666666667" /> | |||
<entry key="..\:/xuekaole/XKLLocal/lib/common/src/main/res/drawable/ic_search.xml" value="0.2212962962962963" /> | |||
<entry key="..\:/xuekaole/XKLLocal/videoplayer/src/main/res/layout/pine_player_media_controller.xml" value="0.125" /> | |||
<entry key="..\:/xuekaole/XKLLocal/videoplayer/src/main/res/layout/pine_player_media_controller_full.xml" value="0.125" /> | |||
<entry key="..\:/xuekaole/XKLLocal/videoplayer/src/main/res/layout/video_popup.xml" value="0.1953125" /> | |||
</map> | |||
</option> | |||
</component> |
@@ -89,10 +89,10 @@ dependencies { | |||
implementation fileTree(include: ['*.jar', "*.aar"], dir: 'libs') | |||
// implementation 'androidx.legacy:legacy-support-v4:1.0.0' | |||
implementation project(path: ':lib:common') | |||
implementation project(path: ':videoplayer') | |||
implementation 'androidx.appcompat:appcompat:1.2.0' | |||
implementation 'com.google.android.material:material:1.3.0' | |||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' | |||
implementation project(path: ':videoplayer') | |||
// implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' | |||
// implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' | |||
// implementation 'androidx.appcompat:appcompat:1.2.0' |
@@ -711,7 +711,8 @@ object DBCourseManager { | |||
while (moveToNext()) { | |||
val videoAnchor = VideoAnchor().apply { | |||
anchor_id = getLong(3) | |||
title = getString(5) | |||
// TODO: 2022/8/24 需要确定数据库打包是否错误,没有错误用4,有错误用5 | |||
title = getString(4) | |||
time = DateUtil.getTimeSecond(getString(2)) | |||
} | |||
videoAnchorList.add(videoAnchor) |
@@ -48,17 +48,24 @@ class CourseLessonFragment : BaseFragmentVM<FragmentCourseLessonBinding, CourseM | |||
if (vm.course.courseType == AppConstants.COURSE_TYPE_ENGLISH_SPOKEN) { | |||
binding.spokenTopLayout.visibility = View.VISIBLE | |||
} | |||
val selectPos = vm.initSelectPosition() | |||
binding.recyclerView.apply { | |||
layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false) | |||
adapterLesson = AdapterLesson(vm).apply { | |||
onItemClick = onLessonClick | |||
//默认选中位置,默认为0 ,如果学习完成则设置为-1 | |||
selectPos = vm.initSelectPosition() | |||
this.selectPos = selectPos | |||
} | |||
adapter = adapterLesson | |||
} | |||
//设置数据 | |||
(binding.recyclerView.adapter as AdapterLesson).setData(vm.allLesson.toMutableList()) | |||
//滑动到学习的位置 | |||
if (selectPos != -1){ | |||
binding.recyclerView.post { | |||
binding.recyclerView.smoothScrollToPosition(selectPos) | |||
} | |||
} | |||
} | |||
override fun loadData() { |
@@ -70,14 +70,22 @@ class MemoTestViewModel : BaseViewModel() { | |||
} | |||
} | |||
/** 查询课程的所有课时 */ | |||
/** 查询课程的所有课时 ,作文显示章节,故只使用了知识点学习所在的课时*/ | |||
fun queryAllLesson() { | |||
if (isAllLessonListInit()) { | |||
showLessonListLivaData.value = 2 | |||
} else { | |||
DataRepository.getCourseAllLesson(dbControlBase, CourseDetail()).compose(diskIo2Main()).subscribe({ | |||
allLessonList = it.toMutableList() | |||
//如果是作文,取知识点的所在的章节即可 | |||
if (memoData.course.coursePackType == AppConstants.COURSEPACK_TYPE_CHINESE_COMPOSITION){ | |||
allLessonList = it.filter { | |||
it.lessonType == AppConstants.LESSON_TYPE_COMPOSITION_KNOWLEDGE | |||
}.toMutableList() | |||
} else { | |||
allLessonList = it.toMutableList() | |||
} | |||
showLessonListLivaData.value = 2 | |||
}, { | |||
it.printStackTrace() | |||
}) | |||
@@ -120,9 +128,8 @@ class MemoTestViewModel : BaseViewModel() { | |||
//查询测试数据 | |||
val testDataList = DBCourseManager.queryMemoTest(dbControlBase, queryLesson, count) | |||
//测试类型 | |||
val examType = if (recordTestType == 1) AppConstants.TEST_TYPE_MEMO else AppConstants.TEST_TYPE_SERVICE_CENTER | |||
return@fromCallable ExamData(memoData.course.subjectId, examType, memoData.course.courseTitle, | |||
saveTitle).apply { | |||
val examType = if (recordTestType == 1) AppConstants.TEST_TYPE_MEMO else AppConstants.TEST_TYPE_SERVICE_CENTER | |||
return@fromCallable ExamData(memoData.course.subjectId, examType, memoData.course.courseTitle, saveTitle).apply { | |||
coursePackId = memoData.course.coursePackId //课程包id, 测试错误上次数据需要 | |||
coursePackType = memoData.course.coursePackType //课程包类型 | |||
courseId = memoData.course.courseId //课程id |
@@ -267,7 +267,7 @@ open class StatisticsTimeTopFragmentViewModel : BaseViewModel() { | |||
} | |||
} | |||
/**实例化增量图标和颜色与正负*/ | |||
/**实例化增量图标和颜色*/ | |||
private fun initIncr(timeStaticItem_1 : TimeStatisticItem, sdIncr : Double) { | |||
timeStaticItem_1.run { | |||
when{ |
@@ -337,12 +337,12 @@ class LearnRuleUtil<T : BaseWord> constructor(private val originLearnList : List | |||
* @return true在 false不存在 | |||
*/ | |||
fun isInExamErrorMap(key : String) : Boolean { | |||
return examErrorsMap?.getOrDefault(key, false) ?: false | |||
return examErrorsMap?.containsKey(key) ?: false | |||
} | |||
/** 是否是在学习的错误列表中 */ | |||
fun isInCurrentErrorMap(key : String) : Boolean { | |||
return currentErrorMap.getOrDefault(key, false) | |||
return currentErrorMap.containsKey(key) | |||
} | |||
/** 判断源数据中的数据是否已经学习完成:由外部调用,originLearnPosition下标的数据为已经取出来学习的数据,只有为第一个的时候,才判断此方法 */ |
@@ -6,7 +6,8 @@ | |||
# http://www.gradle.org/docs/current/userguide/build_environment.html | |||
# Specifies the JVM arguments used for the daemon process. | |||
# The setting is particularly useful for tweaking memory settings. | |||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 | |||
#org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 | |||
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 | |||
# When configured, Gradle will run in incubating parallel mode. | |||
# This option should only be used with decoupled projects. More details, visit | |||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects |
@@ -12,4 +12,4 @@ dependencyResolutionManagement { | |||
rootProject.name = "XklLocal" | |||
include ':app' | |||
include ':lib:common' | |||
include ':videoplayer' | |||
include 'videoplayer' |
@@ -1,6 +1,6 @@ | |||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
package="com.xkl.videoplayer" > | |||
<!-- <uses-permission android:name="android.permission.WRITE_SETTINGS" />--> | |||
<!-- <uses-permission android:name="android.permission.WRITE_SETTINGS" />--> | |||
<application | |||
android:allowBackup="true" | |||
android:label="@string/app_name" |
@@ -1,4 +1,11 @@ | |||
cmake_minimum_required(VERSION 3.4.1) | |||
#if (${ANDROID_ABI} STREQUAL "armeabi-v7a") | |||
# include_directories(${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi) | |||
#elseif (${ANDROID_ABI} STREQUAL "arm64-v8a") | |||
# include_directories(${ANDROID_SYSROOT}/usr/include/aarch64-linux-android) | |||
#else () | |||
# include_directories(${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi) | |||
#endif () | |||
find_library( | |||
log-lib | |||
@@ -64,6 +71,16 @@ PROPERTIES IMPORTED_LOCATION ../../../../libs/${ANDROID_ABI}/libavfilter.so | |||
) | |||
#add_library( | |||
# postproc | |||
# SHARED | |||
# IMPORTED | |||
#) | |||
#set_target_properties(postproc | |||
#PROPERTIES IMPORTED_LOCATION ../../../../libs/${ANDROID_ABI}/lipostproc.so | |||
#) | |||
target_link_libraries(MoviePlayer | |||
avutil |
@@ -205,7 +205,7 @@ public class MoviePlayer { | |||
private long previousPlayTime; //播放上一次记录的时间 | |||
public void PlayPCM(byte[] pcmBuffer, int length, int milliseconds) { | |||
// LogUtil.e("MoviePlayer", "PlayPCM milliseconds = " + milliseconds + " Length=" + length ); | |||
// LogUtil.INSTANCE.e("MoviePlayer", "PlayPCM milliseconds = " + milliseconds + " Length=" + length ); | |||
if (null != audioTrack && AudioTrack.PLAYSTATE_PLAYING == audioTrack.getPlayState()) { | |||
audioTrack.write(pcmBuffer, 0, length); | |||
currentPosition = milliseconds; | |||
@@ -231,7 +231,7 @@ public class MoviePlayer { | |||
if (l - l1 > 3000) { //误差超过三秒降帧 | |||
previousPlayTime = 0; | |||
LogUtil.INSTANCE.e("MoviePlayer localTimeInterval = " + l + " playIntervelTime = " + l1); | |||
LogUtil.INSTANCE.e("MoviePlayer", "localTimeInterval = " + l + " playIntervelTime = " + l1); | |||
if (onPlayStatusChanged != null) { | |||
onPlayStatusChanged.onStatus(10); | |||
} |
@@ -17,7 +17,6 @@ import java.util.List; | |||
/** | |||
* Created by tanghongfeng on 2017/9/18. | |||
* 要播放的多媒体的 | |||
*/ | |||
/** |
@@ -9,7 +9,6 @@ import java.util.ArrayList; | |||
/** | |||
* Created by tanghongfeng on 2018/3/7. | |||
* 要播放的多媒体的数据源的实体类 | |||
*/ | |||
public class PineMediaUriSource implements Serializable { |
@@ -42,7 +42,6 @@ import static com.xkl.videoplayer.component.PinePlayState.STATE_PREPARING; | |||
/** | |||
* 播放器组件,封装播放器细节 | |||
* 封装具体的播放器,通过代理PineMediaPlayerProxy与界面进行交互 | |||
* Created by tanghongfeng on 2017/8/14. | |||
*/ | |||
@@ -714,10 +713,15 @@ public class PineMediaPlayerComponent implements PineMediaWidget.IPineMediaPlaye | |||
LogUtil.INSTANCE.e("=================>", "状态:" + "JPlayer"); | |||
isSwitchDefinition = false; | |||
moviePlayer.JPlay(); | |||
if (moviePlayer.getCachPosition() != 0) { | |||
LogUtil.INSTANCE.e("=================>", "状态:" + "SetPlayTime:" + moviePlayer.getCachPosition()); | |||
moviePlayer.SetPlayTime(moviePlayer.getCachPosition()); | |||
moviePlayer.setCachPosition(0); | |||
// if (moviePlayer.getCachPosition() != 0) { | |||
// LogUtil.INSTANCE.e("=================>", "状态:" + "SetPlayTime:" + moviePlayer.getCachPosition()); | |||
// moviePlayer.SetPlayTime(moviePlayer.getCachPosition()); | |||
// moviePlayer.setCachPosition(0); | |||
// } | |||
if (getCachPositon() != 0) { | |||
LogUtil.INSTANCE.e("=================>", "状态:" + "SetPlayTime:" + getCachPositon()); | |||
moviePlayer.SetPlayTime(getCachPositon()); | |||
setCachPosition(0); | |||
} | |||
} else { | |||
LogUtil.INSTANCE.e("=================>", "状态:" + "JResume:"); | |||
@@ -861,13 +865,20 @@ public class PineMediaPlayerComponent implements PineMediaWidget.IPineMediaPlaye | |||
moviePlayer.setCurrentPosition(position); | |||
} | |||
} | |||
private int chachePosition = 0 ; | |||
public void setCachPosition(int position) { | |||
if (moviePlayer == null){ | |||
chachePosition = position ; | |||
return; | |||
} | |||
moviePlayer.setCachPosition(position); | |||
} | |||
@Override | |||
public int getCachPositon() { | |||
if (moviePlayer == null){ | |||
return chachePosition; | |||
} | |||
return moviePlayer.getCachPosition(); | |||
} | |||
@@ -13,7 +13,6 @@ import java.util.Map; | |||
/** | |||
* Created by tanghongfeng on 2018/4/2. | |||
* 播放器组件代理类 | |||
*/ | |||
public class PineMediaPlayerProxy implements PineMediaWidget.IPineMediaPlayer, PineMediaWidget.IPineMediaPlayerComponent { |
@@ -12,7 +12,6 @@ import java.util.Map; | |||
/** | |||
* Created by tanghongfeng on 2017/8/28. | |||
* 播放器组件接口集合 | |||
*/ | |||
public class PineMediaWidget { |
@@ -1065,7 +1065,7 @@ public class PineMediaController extends RelativeLayout implements PineMediaWidg | |||
mWaitingProgressViewHolder = new PineWaitingProgressViewHolder(); | |||
} | |||
// 内置右侧Views | |||
// LogUtil.INSTANCE.e("attachToParentView",mRightViewHolderList.toString()); | |||
LogUtil.INSTANCE.e("attachToParentView",mRightViewHolderList.toString()); | |||
if (mRightViewHolderList != null && mRightViewHolderList.size() > 0) { | |||
mRightViewContainer = new RelativeLayout(getContext()); | |||
for (int i = 0; i < mRightViewHolderList.size(); i++) { |
@@ -163,14 +163,14 @@ public class DefaultVideoControllerAdapter extends PineMediaController.AbstractM | |||
mediaListBtn.setVisibility(View.GONE); | |||
} | |||
mDDefinitionBtn = (TextView) mDFullControllerView.findViewById(R.id.media_definition_text); | |||
PineMediaPlayerBean pineMediaPlayerBean = player.getMediaPlayerBean(); | |||
if (hasDefinitionList(pineMediaPlayerBean) && mDEnableDefinition) { | |||
rightViewControlBtnList.add(mDDefinitionBtn); | |||
mDDefinitionBtn.setVisibility(View.VISIBLE); | |||
mDDefinitionBtn.setText(getDefinitionName(pineMediaPlayerBean.getCurrentDefinition())); | |||
} else { | |||
// PineMediaPlayerBean pineMediaPlayerBean = player.getMediaPlayerBean(); | |||
// if (hasDefinitionList(pineMediaPlayerBean) && mDEnableDefinition) { | |||
// rightViewControlBtnList.add(mDDefinitionBtn); | |||
// mDDefinitionBtn.setVisibility(View.VISIBLE); | |||
// mDDefinitionBtn.setText(getDefinitionName(pineMediaPlayerBean.getCurrentDefinition())); | |||
// } else { | |||
mDDefinitionBtn.setVisibility(View.GONE); | |||
} | |||
// } | |||
if (rightViewControlBtnList.size() > 0) { | |||
mDFullControllerViewHolder.setRightViewControlBtnList(rightViewControlBtnList); | |||
} | |||
@@ -406,7 +406,8 @@ public class DefaultVideoControllerAdapter extends PineMediaController.AbstractM | |||
} | |||
private boolean hasDefinitionList(PineMediaPlayerBean pineMediaPlayerBean) { | |||
return pineMediaPlayerBean != null && pineMediaPlayerBean.getMediaUriSourceList().size() > 1; | |||
return pineMediaPlayerBean != null; | |||
// && pineMediaPlayerBean.getMediaUriSourceList().size() > 1; | |||
} | |||
public String getCurMediaCode() { |
@@ -202,7 +202,8 @@ | |||
android:layout_centerVertical="true" | |||
android:textSize="14sp" | |||
android:text="@string/pine_media_definition_sd" | |||
android:textColor="@color/pine_controller_text"/> | |||
android:textColor="@color/pine_controller_text" | |||
android:visibility="gone"/> | |||
<ImageView | |||
android:id="@+id/full_screen_btn" |