Sfoglia il codice sorgente

集成视频插件,将视频相关功能独立出来(但是x86不兼容)

zengjiebin 7 anni fa
parent
commit
d68d55d54e
100 ha cambiato i file con 5224 aggiunte e 1698 eliminazioni
  1. 1 0
      .idea/gradle.xml
  2. 3 12
      app/build.gradle
  3. 9 1
      app/proguard-rules.pro
  4. 0 10
      app/src/main/AndroidManifest.xml
  5. 1 1
      app/src/main/java/com/sheep/gamegroup/absBase/AbsObserver.java
  6. 15 15
      app/src/main/java/com/sheep/gamegroup/greendao/download/DaoMaster.java
  7. 61 61
      app/src/main/java/com/sheep/gamegroup/greendao/download/DaoSession.java
  8. 10 0
      app/src/main/java/com/sheep/gamegroup/model/api/ApiService.java
  9. 8 0
      app/src/main/java/com/sheep/gamegroup/model/entity/DiscoveryVideo.java
  10. 0 489
      app/src/main/java/com/sheep/gamegroup/module/find/activity/ActEditVideo.java
  11. 43 20
      app/src/main/java/com/sheep/gamegroup/module/find/activity/ActMediaChoose.java
  12. 1 1
      app/src/main/java/com/sheep/gamegroup/module/find/fragment/FgtMediaPickerVideo.java
  13. 127 0
      app/src/main/java/com/sheep/gamegroup/module/plugin/module/ClientPackage.java
  14. 18 0
      app/src/main/java/com/sheep/gamegroup/module/plugin/module/Plugin.java
  15. 166 0
      app/src/main/java/com/sheep/gamegroup/module/plugin/util/PluginUtil.java
  16. 1 1
      app/src/main/java/com/sheep/gamegroup/util/ConnectAddress.java
  17. 40 18
      app/src/main/java/com/sheep/gamegroup/util/Jump2View.java
  18. 13 0
      app/src/main/java/com/sheep/gamegroup/util/ListUtil.java
  19. 27 13
      app/src/main/java/com/sheep/gamegroup/util/MediaMetadataRetrieverUtil.java
  20. 2 72
      app/src/main/java/com/sheep/gamegroup/util/TestUtil.java
  21. 0 17
      app/src/main/java/com/sheep/gamegroup/util/ViewUtil.java
  22. 513 506
      app/src/main/java/com/sheep/gamegroup/view/activity/ActCutVideo.java
  23. 1 0
      app/src/main/java/com/sheep/gamegroup/view/activity/ActMain.java
  24. 103 106
      app/src/main/java/com/sheep/gamegroup/view/activity/ActVideoDetail.java
  25. 2 1
      app/src/main/java/com/sheep/gamegroup/view/adapter/AdpVideo.java
  26. 279 268
      app/src/main/java/com/sheep/gamegroup/view/customview/VideoFramesView.java
  27. 4 50
      app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java
  28. 6 0
      app/src/main/java/org/afinal/simplecache/ApiKey.java
  29. 0 1
      app/src/main/res/layout/act_video_detail.xml
  30. 0 3
      app/src/sheeptestjiguang/res/values/strings.xml
  31. 2 1
      build.gradle
  32. 14 0
      media/.gitignore
  33. 1 0
      media/app/.gitignore
  34. 101 0
      media/app/build.gradle
  35. 23 0
      media/app/proguard-rules.pro
  36. 26 0
      media/app/src/androidTest/java/com/kfzs/cfyl/media/ExampleInstrumentedTest.java
  37. 29 0
      media/app/src/main/AndroidManifest.xml
  38. BIN
      media/app/src/main/assets/edgy_amber.png
  39. BIN
      media/app/src/main/assets/filmstock.png
  40. BIN
      media/app/src/main/assets/foggy_night.png
  41. BIN
      media/app/src/main/assets/hehe.jpg
  42. BIN
      media/app/src/main/assets/late_sunset.png
  43. BIN
      media/app/src/main/assets/mapping0.jpg
  44. BIN
      media/app/src/main/assets/soft_warming.png
  45. BIN
      media/app/src/main/assets/wildbird.png
  46. 146 0
      media/app/src/main/java/com/kfzs/cfyl/media/BaseActivity.java
  47. 36 0
      media/app/src/main/java/com/kfzs/cfyl/media/BaseContainerActivity.java
  48. 103 0
      media/app/src/main/java/com/kfzs/cfyl/media/BaseFragment.java
  49. 143 0
      media/app/src/main/java/com/kfzs/cfyl/media/MediaApp.java
  50. 311 0
      media/app/src/main/java/com/kfzs/cfyl/media/activity/ActCutVideo.java
  51. 322 0
      media/app/src/main/java/com/kfzs/cfyl/media/activity/ActEditVideo.java
  52. 21 0
      media/app/src/main/java/com/kfzs/cfyl/media/activity/MainActivity.java
  53. 11 0
      media/app/src/main/java/com/kfzs/cfyl/media/api/Filterble.java
  54. 11 0
      media/app/src/main/java/com/kfzs/cfyl/media/api/IFilter.java
  55. 10 0
      media/app/src/main/java/com/kfzs/cfyl/media/api/IdChooser.java
  56. 66 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/BeautifyFilter.java
  57. 198 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/ColorBalanceFilter.java
  58. 37 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/Filter.java
  59. 119 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/Lp.java
  60. 48 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/Size.java
  61. 49 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/VideoFrame.java
  62. 59 0
      media/app/src/main/java/com/kfzs/cfyl/media/bean/WaveFilter.java
  63. 411 0
      media/app/src/main/java/com/kfzs/cfyl/media/customview/VideoFramesView.java
  64. 56 0
      media/app/src/main/java/com/kfzs/cfyl/media/dialog/DialogProgress.java
  65. 39 27
      app/src/main/java/com/sheep/gamegroup/module/find/fragment/FgtChooseEditList.java
  66. 69 0
      media/app/src/main/java/com/kfzs/cfyl/media/fragment/FgtDiscoveryTopic.java
  67. 50 0
      media/app/src/main/java/com/kfzs/cfyl/media/glide/CustomGlideModule.java
  68. 2 2
      app/src/main/java/com/sheep/gamegroup/util/glide/FilterTransform.java
  69. 45 0
      media/app/src/main/java/com/kfzs/cfyl/media/glide/VideoFrameTransform.java
  70. 25 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/BitmapUtil.java
  71. 21 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/FileUtil.java
  72. 33 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/G.java
  73. 28 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/Jump2View.java
  74. 25 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/KeyEventUtil.java
  75. 44 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/LayoutParamsUtil.java
  76. 228 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/ListUtil.java
  77. 324 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/VideoUtil.java
  78. 106 0
      media/app/src/main/java/com/kfzs/cfyl/media/util/ViewUtil.java
  79. 9 0
      media/app/src/main/res/color/selector_color_white_40.xml
  80. 34 0
      media/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  81. 9 0
      media/app/src/main/res/drawable-v24/shape_black_solid_rectangle_top_6.xml
  82. BIN
      media/app/src/main/res/drawable-xhdpi/narrow_back_white.webp
  83. BIN
      media/app/src/main/res/drawable-xxhdpi/narrow_back_black.webp
  84. BIN
      media/app/src/main/res/drawable-xxhdpi/qiandao.webp
  85. BIN
      media/app/src/main/res/drawable-xxhdpi/sheep_logo.png
  86. BIN
      media/app/src/main/res/drawable-xxhdpi/sheep_logo_3.png
  87. 10 0
      media/app/src/main/res/drawable/button_full_normal_gray.xml
  88. 9 0
      media/app/src/main/res/drawable/button_full_normal_main_click.xml
  89. 170 0
      media/app/src/main/res/drawable/ic_launcher_background.xml
  90. 9 0
      media/app/src/main/res/drawable/selector_button_full_main.xml
  91. 5 0
      media/app/src/main/res/drawable/shape_oval_main.xml
  92. 6 0
      media/app/src/main/res/drawable/shape_white_20_solid_rectangle_15.xml
  93. 6 0
      media/app/src/main/res/drawable/shape_white_solid_rectangle_5.xml
  94. 12 0
      media/app/src/main/res/drawable/sp_bg_gradient_rectangle_blue.xml
  95. 2 2
      app/src/main/res/layout/act_cut_video.xml
  96. 86 0
      media/app/src/main/res/layout/act_edit_video.xml
  97. 5 0
      media/app/src/main/res/layout/common_container.xml
  98. 6 0
      media/app/src/main/res/layout/common_rv.xml
  99. 0 0
      media/app/src/main/res/layout/custom_video_frames_view.xml
  100. 0 0
      media/app/src/main/res/layout/dialog_loading.xml

+ 1 - 0
.idea/gradle.xml

@@ -10,6 +10,7 @@
             <option value="$PROJECT_DIR$" />
             <option value="$PROJECT_DIR$/WaterWaveProgress" />
             <option value="$PROJECT_DIR$/app" />
+            <option value="$PROJECT_DIR$/media/share_library" />
             <option value="$PROJECT_DIR$/ucrop" />
             <option value="$PROJECT_DIR$/view" />
           </set>

+ 3 - 12
app/build.gradle

@@ -1,6 +1,7 @@
 apply plugin: 'com.android.application'
 apply plugin: 'com.jakewharton.butterknife'
 apply plugin: 'org.greenrobot.greendao'
+apply plugin: 'com.didi.virtualapk.host'
 //apply plugin: 'realm-android'//Realm数据库
 android {
     compileSdkVersion ANDROID_COMPILE_SDK_VERSION as int
@@ -78,7 +79,6 @@ android {
             buildConfigField "String", "DUANDUAN_GRAPH", '"sheeptest"'
             resValue "string", "app_name", "小绵羊测试"
             buildConfigField "boolean", "XXTEA_ENCRYPT", 'true'
-            buildConfigField "String", "API_DOMAIN", '"app.ss.kfzs.com"'
             signingConfig signingConfigs.config
         }
         sheeptestjiguang {
@@ -92,7 +92,6 @@ android {
             buildConfigField "String", "DUANDUAN_GRAPH", '"sheeptestjiguang"'
             resValue "string", "app_name", "小绵羊极光测试"
             buildConfigField "boolean", "XXTEA_ENCRYPT", 'true'
-            buildConfigField "String", "API_DOMAIN", '"app.ss.kfzs.com"'
             signingConfig signingConfigs.config
         }
         sheep {
@@ -106,7 +105,6 @@ android {
             buildConfigField "String", "DUANDUAN_GRAPH", '"sheep"'
             resValue "string", "app_name", "小绵羊"
             buildConfigField "boolean", "XXTEA_ENCRYPT", 'true'
-            buildConfigField "String", "API_DOMAIN", '"app.ss.kfzs.com"'
             signingConfig signingConfigs.config
 
         }
@@ -283,9 +281,6 @@ dependencies {
 
     //implementation 'com.umeng.sdk:analytics:latest.integration'
 
-    //fast json
-    implementation 'com.alibaba:fastjson:1.2.52'
-
     //添加半袋米相关
     implementation(name: 'appstoreutils-201810101432', ext: 'aar')
     implementation project(':view')
@@ -405,7 +400,6 @@ dependencies {
     //
 
     //    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
-    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.34'
 
     //有米科技
     implementation(name: 'YoumiSdk_v8.3.0_2018-09-20', ext: 'aar')
@@ -428,11 +422,8 @@ dependencies {
     implementation('com.qiniu:qiniu-android-sdk:7.3.13') {
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
     }
-    //All arch: armeabi, armeabi-v7a, arm64-v8a, mips, x86
-    implementation 'org.wysaid:gpuimage-plus:2.5.1'
-    //Pure graphics lib without ffmpeg. (all arch for branch 'min')
-//    implementation 'org.wysaid:gpuimage-plus:2.5.1-min'
-//    implementation project(':library')
+    implementation project(':media/share_library')
+    implementation 'com.didi.virtualapk:core:0.9.8'
 }
 
 static def releaseTime() {

+ 9 - 1
app/proguard-rules.pro

@@ -462,4 +462,12 @@
 #==================compile 'com.haibin:calendarview:3.4.4'==========================
  -keepclasseswithmembers class * {
      public <init>(android.content.Context);
- }
+ }
+
+#==================插件化框架 https://github.com/didi/VirtualAPK==========================
+ -keep class com.didi.virtualapk.internal.VAInstrumentation { *; }
+ -keep class com.didi.virtualapk.internal.PluginContentResolver { *; }
+
+ -dontwarn com.didi.virtualapk.**
+ -dontwarn android.**
+ -keep class android.** { *; }

+ 0 - 10
app/src/main/AndroidManifest.xml

@@ -471,16 +471,6 @@
             android:screenOrientation="user"
             android:theme="@style/AppTheme.noTitleBar" />
         <activity
-            android:name="com.sheep.gamegroup.view.activity.ActCutVideo"
-            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
-            android:screenOrientation="portrait"
-            android:theme="@style/AppTheme.noTitleBar" />
-        <activity
-            android:name="com.sheep.gamegroup.module.find.activity.ActEditVideo"
-            android:configChanges="orientation|keyboardHidden|navigation|screenSize"
-            android:screenOrientation="user"
-            android:theme="@style/AppTheme.noTitleBar" />
-        <activity
             android:name="com.sheep.gamegroup.view.activity.ActInputAndPickerImg"
             android:theme="@style/AppTheme.translucent" />
         <activity

+ 1 - 1
app/src/main/java/com/sheep/gamegroup/absBase/AbsObserver.java

@@ -10,7 +10,7 @@ import io.reactivex.disposables.Disposable;
  * Created by realicing on 2018/11/19.
  * realicing@sina.com
  */
-public abstract class AbsObserver<T> implements Observer<T> {
+public class AbsObserver<T> implements Observer<T> {
     @Override
     public void onSubscribe(Disposable d) {
 

+ 15 - 15
app/src/main/java/com/sheep/gamegroup/greendao/download/DaoMaster.java

@@ -21,26 +21,26 @@ public class DaoMaster extends AbstractDaoMaster {
 
     /** Creates underlying database table using DAOs. */
     public static void createAllTables(Database db, boolean ifNotExists) {
-        ProcessRecordDao.createTable(db, ifNotExists);
-        AppdownloadBeanDao.createTable(db, ifNotExists);
-        SdkLoginUserDao.createTable(db, ifNotExists);
-        ScreenShotRecordDao.createTable(db, ifNotExists);
         AcceptTaskRecordDao.createTable(db, ifNotExists);
         AccountDao.createTable(db, ifNotExists);
-        SearchRecordDao.createTable(db, ifNotExists);
+        AppdownloadBeanDao.createTable(db, ifNotExists);
         DownLoadInfoDao.createTable(db, ifNotExists);
+        ProcessRecordDao.createTable(db, ifNotExists);
+        ScreenShotRecordDao.createTable(db, ifNotExists);
+        SdkLoginUserDao.createTable(db, ifNotExists);
+        SearchRecordDao.createTable(db, ifNotExists);
     }
 
     /** Drops underlying database table using DAOs. */
     public static void dropAllTables(Database db, boolean ifExists) {
-        ProcessRecordDao.dropTable(db, ifExists);
-        AppdownloadBeanDao.dropTable(db, ifExists);
-        SdkLoginUserDao.dropTable(db, ifExists);
-        ScreenShotRecordDao.dropTable(db, ifExists);
         AcceptTaskRecordDao.dropTable(db, ifExists);
         AccountDao.dropTable(db, ifExists);
-        SearchRecordDao.dropTable(db, ifExists);
+        AppdownloadBeanDao.dropTable(db, ifExists);
         DownLoadInfoDao.dropTable(db, ifExists);
+        ProcessRecordDao.dropTable(db, ifExists);
+        ScreenShotRecordDao.dropTable(db, ifExists);
+        SdkLoginUserDao.dropTable(db, ifExists);
+        SearchRecordDao.dropTable(db, ifExists);
     }
 
     /**
@@ -59,14 +59,14 @@ public class DaoMaster extends AbstractDaoMaster {
 
     public DaoMaster(Database db) {
         super(db, SCHEMA_VERSION);
-        registerDaoClass(ProcessRecordDao.class);
-        registerDaoClass(AppdownloadBeanDao.class);
-        registerDaoClass(SdkLoginUserDao.class);
-        registerDaoClass(ScreenShotRecordDao.class);
         registerDaoClass(AcceptTaskRecordDao.class);
         registerDaoClass(AccountDao.class);
-        registerDaoClass(SearchRecordDao.class);
+        registerDaoClass(AppdownloadBeanDao.class);
         registerDaoClass(DownLoadInfoDao.class);
+        registerDaoClass(ProcessRecordDao.class);
+        registerDaoClass(ScreenShotRecordDao.class);
+        registerDaoClass(SdkLoginUserDao.class);
+        registerDaoClass(SearchRecordDao.class);
     }
 
     public DaoSession newSession() {

+ 61 - 61
app/src/main/java/com/sheep/gamegroup/greendao/download/DaoSession.java

@@ -8,23 +8,23 @@ import org.greenrobot.greendao.database.Database;
 import org.greenrobot.greendao.identityscope.IdentityScopeType;
 import org.greenrobot.greendao.internal.DaoConfig;
 
-import com.sheep.gamegroup.greendao.download.ProcessRecord;
-import com.sheep.gamegroup.greendao.download.AppdownloadBean;
-import com.sheep.gamegroup.greendao.download.SdkLoginUser;
-import com.sheep.gamegroup.greendao.download.ScreenShotRecord;
 import com.sheep.gamegroup.greendao.download.AcceptTaskRecord;
 import com.sheep.gamegroup.greendao.download.Account;
-import com.sheep.gamegroup.greendao.download.SearchRecord;
+import com.sheep.gamegroup.greendao.download.AppdownloadBean;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
+import com.sheep.gamegroup.greendao.download.ProcessRecord;
+import com.sheep.gamegroup.greendao.download.ScreenShotRecord;
+import com.sheep.gamegroup.greendao.download.SdkLoginUser;
+import com.sheep.gamegroup.greendao.download.SearchRecord;
 
-import com.sheep.gamegroup.greendao.download.ProcessRecordDao;
-import com.sheep.gamegroup.greendao.download.AppdownloadBeanDao;
-import com.sheep.gamegroup.greendao.download.SdkLoginUserDao;
-import com.sheep.gamegroup.greendao.download.ScreenShotRecordDao;
 import com.sheep.gamegroup.greendao.download.AcceptTaskRecordDao;
 import com.sheep.gamegroup.greendao.download.AccountDao;
-import com.sheep.gamegroup.greendao.download.SearchRecordDao;
+import com.sheep.gamegroup.greendao.download.AppdownloadBeanDao;
 import com.sheep.gamegroup.greendao.download.DownLoadInfoDao;
+import com.sheep.gamegroup.greendao.download.ProcessRecordDao;
+import com.sheep.gamegroup.greendao.download.ScreenShotRecordDao;
+import com.sheep.gamegroup.greendao.download.SdkLoginUserDao;
+import com.sheep.gamegroup.greendao.download.SearchRecordDao;
 
 // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
 
@@ -35,112 +35,112 @@ import com.sheep.gamegroup.greendao.download.DownLoadInfoDao;
  */
 public class DaoSession extends AbstractDaoSession {
 
-    private final DaoConfig processRecordDaoConfig;
-    private final DaoConfig appdownloadBeanDaoConfig;
-    private final DaoConfig sdkLoginUserDaoConfig;
-    private final DaoConfig screenShotRecordDaoConfig;
     private final DaoConfig acceptTaskRecordDaoConfig;
     private final DaoConfig accountDaoConfig;
-    private final DaoConfig searchRecordDaoConfig;
+    private final DaoConfig appdownloadBeanDaoConfig;
     private final DaoConfig downLoadInfoDaoConfig;
+    private final DaoConfig processRecordDaoConfig;
+    private final DaoConfig screenShotRecordDaoConfig;
+    private final DaoConfig sdkLoginUserDaoConfig;
+    private final DaoConfig searchRecordDaoConfig;
 
-    private final ProcessRecordDao processRecordDao;
-    private final AppdownloadBeanDao appdownloadBeanDao;
-    private final SdkLoginUserDao sdkLoginUserDao;
-    private final ScreenShotRecordDao screenShotRecordDao;
     private final AcceptTaskRecordDao acceptTaskRecordDao;
     private final AccountDao accountDao;
-    private final SearchRecordDao searchRecordDao;
+    private final AppdownloadBeanDao appdownloadBeanDao;
     private final DownLoadInfoDao downLoadInfoDao;
+    private final ProcessRecordDao processRecordDao;
+    private final ScreenShotRecordDao screenShotRecordDao;
+    private final SdkLoginUserDao sdkLoginUserDao;
+    private final SearchRecordDao searchRecordDao;
 
     public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
             daoConfigMap) {
         super(db);
 
-        processRecordDaoConfig = daoConfigMap.get(ProcessRecordDao.class).clone();
-        processRecordDaoConfig.initIdentityScope(type);
+        acceptTaskRecordDaoConfig = daoConfigMap.get(AcceptTaskRecordDao.class).clone();
+        acceptTaskRecordDaoConfig.initIdentityScope(type);
+
+        accountDaoConfig = daoConfigMap.get(AccountDao.class).clone();
+        accountDaoConfig.initIdentityScope(type);
 
         appdownloadBeanDaoConfig = daoConfigMap.get(AppdownloadBeanDao.class).clone();
         appdownloadBeanDaoConfig.initIdentityScope(type);
 
-        sdkLoginUserDaoConfig = daoConfigMap.get(SdkLoginUserDao.class).clone();
-        sdkLoginUserDaoConfig.initIdentityScope(type);
+        downLoadInfoDaoConfig = daoConfigMap.get(DownLoadInfoDao.class).clone();
+        downLoadInfoDaoConfig.initIdentityScope(type);
+
+        processRecordDaoConfig = daoConfigMap.get(ProcessRecordDao.class).clone();
+        processRecordDaoConfig.initIdentityScope(type);
 
         screenShotRecordDaoConfig = daoConfigMap.get(ScreenShotRecordDao.class).clone();
         screenShotRecordDaoConfig.initIdentityScope(type);
 
-        acceptTaskRecordDaoConfig = daoConfigMap.get(AcceptTaskRecordDao.class).clone();
-        acceptTaskRecordDaoConfig.initIdentityScope(type);
-
-        accountDaoConfig = daoConfigMap.get(AccountDao.class).clone();
-        accountDaoConfig.initIdentityScope(type);
+        sdkLoginUserDaoConfig = daoConfigMap.get(SdkLoginUserDao.class).clone();
+        sdkLoginUserDaoConfig.initIdentityScope(type);
 
         searchRecordDaoConfig = daoConfigMap.get(SearchRecordDao.class).clone();
         searchRecordDaoConfig.initIdentityScope(type);
 
-        downLoadInfoDaoConfig = daoConfigMap.get(DownLoadInfoDao.class).clone();
-        downLoadInfoDaoConfig.initIdentityScope(type);
-
-        processRecordDao = new ProcessRecordDao(processRecordDaoConfig, this);
-        appdownloadBeanDao = new AppdownloadBeanDao(appdownloadBeanDaoConfig, this);
-        sdkLoginUserDao = new SdkLoginUserDao(sdkLoginUserDaoConfig, this);
-        screenShotRecordDao = new ScreenShotRecordDao(screenShotRecordDaoConfig, this);
         acceptTaskRecordDao = new AcceptTaskRecordDao(acceptTaskRecordDaoConfig, this);
         accountDao = new AccountDao(accountDaoConfig, this);
-        searchRecordDao = new SearchRecordDao(searchRecordDaoConfig, this);
+        appdownloadBeanDao = new AppdownloadBeanDao(appdownloadBeanDaoConfig, this);
         downLoadInfoDao = new DownLoadInfoDao(downLoadInfoDaoConfig, this);
+        processRecordDao = new ProcessRecordDao(processRecordDaoConfig, this);
+        screenShotRecordDao = new ScreenShotRecordDao(screenShotRecordDaoConfig, this);
+        sdkLoginUserDao = new SdkLoginUserDao(sdkLoginUserDaoConfig, this);
+        searchRecordDao = new SearchRecordDao(searchRecordDaoConfig, this);
 
-        registerDao(ProcessRecord.class, processRecordDao);
-        registerDao(AppdownloadBean.class, appdownloadBeanDao);
-        registerDao(SdkLoginUser.class, sdkLoginUserDao);
-        registerDao(ScreenShotRecord.class, screenShotRecordDao);
         registerDao(AcceptTaskRecord.class, acceptTaskRecordDao);
         registerDao(Account.class, accountDao);
-        registerDao(SearchRecord.class, searchRecordDao);
+        registerDao(AppdownloadBean.class, appdownloadBeanDao);
         registerDao(DownLoadInfo.class, downLoadInfoDao);
+        registerDao(ProcessRecord.class, processRecordDao);
+        registerDao(ScreenShotRecord.class, screenShotRecordDao);
+        registerDao(SdkLoginUser.class, sdkLoginUserDao);
+        registerDao(SearchRecord.class, searchRecordDao);
     }
     
     public void clear() {
-        processRecordDaoConfig.clearIdentityScope();
-        appdownloadBeanDaoConfig.clearIdentityScope();
-        sdkLoginUserDaoConfig.clearIdentityScope();
-        screenShotRecordDaoConfig.clearIdentityScope();
         acceptTaskRecordDaoConfig.clearIdentityScope();
         accountDaoConfig.clearIdentityScope();
-        searchRecordDaoConfig.clearIdentityScope();
+        appdownloadBeanDaoConfig.clearIdentityScope();
         downLoadInfoDaoConfig.clearIdentityScope();
+        processRecordDaoConfig.clearIdentityScope();
+        screenShotRecordDaoConfig.clearIdentityScope();
+        sdkLoginUserDaoConfig.clearIdentityScope();
+        searchRecordDaoConfig.clearIdentityScope();
     }
 
-    public ProcessRecordDao getProcessRecordDao() {
-        return processRecordDao;
+    public AcceptTaskRecordDao getAcceptTaskRecordDao() {
+        return acceptTaskRecordDao;
+    }
+
+    public AccountDao getAccountDao() {
+        return accountDao;
     }
 
     public AppdownloadBeanDao getAppdownloadBeanDao() {
         return appdownloadBeanDao;
     }
 
-    public SdkLoginUserDao getSdkLoginUserDao() {
-        return sdkLoginUserDao;
+    public DownLoadInfoDao getDownLoadInfoDao() {
+        return downLoadInfoDao;
     }
 
-    public ScreenShotRecordDao getScreenShotRecordDao() {
-        return screenShotRecordDao;
+    public ProcessRecordDao getProcessRecordDao() {
+        return processRecordDao;
     }
 
-    public AcceptTaskRecordDao getAcceptTaskRecordDao() {
-        return acceptTaskRecordDao;
+    public ScreenShotRecordDao getScreenShotRecordDao() {
+        return screenShotRecordDao;
     }
 
-    public AccountDao getAccountDao() {
-        return accountDao;
+    public SdkLoginUserDao getSdkLoginUserDao() {
+        return sdkLoginUserDao;
     }
 
     public SearchRecordDao getSearchRecordDao() {
         return searchRecordDao;
     }
 
-    public DownLoadInfoDao getDownLoadInfoDao() {
-        return downLoadInfoDao;
-    }
-
 }

+ 10 - 0
app/src/main/java/com/sheep/gamegroup/model/api/ApiService.java

@@ -1561,5 +1561,15 @@ public interface ApiService {
     @GET(ApiKey.getVideoTopic)
     Observable<BaseMessage> getVideoTopic();
 //---------------------------end 小绵羊3.4.5 视频-------------------------------------
+//---------------------------start 插件配置相关-------------------------------------
+    /**
+     * 客户端插件更新/插件获取
+     * package_name * string (query) 包名
+     * type * string (query) 类型
+     * version * string (query) 版本号
+     */
+    @GET(ApiKey.getPackageVersion)
+    Observable<BaseMessage> getPackageVersion(@Query("package_name") String package_name, @Query("type") String type, @Query("version") int version);
+//---------------------------end 插件配置相关-------------------------------------
 
 }

+ 8 - 0
app/src/main/java/com/sheep/gamegroup/model/entity/DiscoveryVideo.java

@@ -1,5 +1,7 @@
 package com.sheep.gamegroup.model.entity;
 
+import android.support.annotation.Nullable;
+
 import java.io.Serializable;
 
 /**
@@ -221,4 +223,10 @@ public class DiscoveryVideo implements Serializable {
     public void setIs_focus_user(boolean is_focus_user) {
         this.is_focus_user = is_focus_user;
     }
+
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        return obj instanceof DiscoveryVideo && ((DiscoveryVideo) obj).getId() == id;
+    }
 }

+ 0 - 489
app/src/main/java/com/sheep/gamegroup/module/find/activity/ActEditVideo.java

@@ -1,489 +0,0 @@
-package com.sheep.gamegroup.module.find.activity;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.MediaPlayer;
-import android.net.Uri;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v7.widget.AppCompatButton;
-import android.util.Log;
-import android.view.View;
-import android.widget.Button;
-import android.widget.LinearLayout;
-import android.widget.SeekBar;
-
-import com.kfzs.duanduan.utils.StatusBarUtils;
-import com.sheep.gamegroup.absBase.AbsObserver;
-import com.sheep.gamegroup.absBase.BaseContainerActivity;
-import com.sheep.gamegroup.module.find.util.Filterble;
-import com.sheep.gamegroup.module.find.util.IFilter;
-import com.sheep.gamegroup.module.find.bean.Size;
-import com.sheep.gamegroup.module.find.fragment.FgtChooseEditList;
-import com.sheep.gamegroup.model.entity.Video;
-import com.sheep.gamegroup.util.BitmapUtil;
-import com.sheep.gamegroup.util.DataUtil;
-import com.sheep.gamegroup.util.LogUtil;
-import com.sheep.gamegroup.util.TestUtil;
-import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.util.viewHelper.CacheImageUtil;
-import com.sheep.jiuyan.samllsheep.R;
-import com.sheep.jiuyan.samllsheep.SheepApp;
-import com.sheep.jiuyan.samllsheep.utils.G;
-
-import org.greenrobot.eventbus.EventBus;
-import org.wysaid.common.Common;
-import org.wysaid.myUtils.ImageUtil;
-import org.wysaid.nativePort.CGEFFmpegNativeLibrary;
-import org.wysaid.nativePort.CGEFrameRenderer;
-import org.wysaid.nativePort.CGENativeLibrary;
-import org.wysaid.view.VideoPlayerGLSurfaceView;
-
-import java.io.File;
-import java.util.Locale;
-
-import butterknife.BindView;
-import io.reactivex.Observable;
-import io.reactivex.ObservableEmitter;
-import io.reactivex.ObservableOnSubscribe;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.schedulers.Schedulers;
-import rx.functions.Action1;
-
-/**
- * Created by realicing on 2018/11/9.
- * realicing@sina.com
- * 编辑视频
- */
-public class ActEditVideo extends BaseContainerActivity implements Filterble {
-
-    @Override
-    protected void onCreate(@Nullable Bundle savedInstanceState) {
-        StatusBarUtils.setTranslucent(this);
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    protected int getLayoutId() {
-        return R.layout.act_edit_video;
-    }
-
-    @BindView(R.id.videoGLSurfaceView)
-    VideoPlayerGLSurfaceView mPlayerView;
-
-    private Video data;
-
-    private String mCurrentConfig;
-    private float mIntensity = 1.0f;
-
-    public static final int REQUEST_CODE_PICK_VIDEO = 1;
-
-    private VideoPlayerGLSurfaceView.PlayCompletionCallback playCompletionCallback = new VideoPlayerGLSurfaceView.PlayCompletionCallback() {
-        @Override
-        public void playComplete(MediaPlayer player) {
-            Log.i(Common.LOG_TAG, "The video playing is over, restart...");
-            player.start();
-        }
-
-        @Override
-        public boolean playFailed(MediaPlayer player, final int what, final int extra) {
-            if (TestUtil.isDev())
-                G.showToast(String.format(Locale.CHINA, "播放出错!错误码: %d, %d", what, extra));
-            else
-                G.showToast("播放出错,请稍候重试");
-            return true;
-        }
-    };
-
-    @Override
-    public void initView() {
-        if (this instanceof BaseContainerActivity) {
-            super.initView();
-        }
-        data = DataUtil.getObject(getIntent(), Video.class);
-        mPlayerView.setZOrderOnTop(false);
-        mPlayerView.setZOrderMediaOverlay(true);
-
-
-        mPlayerView.setPlayerInitializeCallback(new VideoPlayerGLSurfaceView.PlayerInitializeCallback() {
-            @Override
-            public void initPlayer(final MediaPlayer player) {
-                //针对网络视频进行进度检查
-                player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
-                    @Override
-                    public void onBufferingUpdate(MediaPlayer mp, int percent) {
-                        Log.i(Common.LOG_TAG, "Buffer update: " + percent);
-                        if (percent == 100) {
-                            Log.i(Common.LOG_TAG, "缓冲完毕!");
-                            player.setOnBufferingUpdateListener(null);
-                        }
-                    }
-                });
-            }
-        });
-
-        mPlayerView.setVideoUri(Uri.parse(data.getFilePath()), new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
-            @Override
-            public void playPrepared(MediaPlayer player) {
-                Log.i(Common.LOG_TAG, "The video is prepared to play");
-                player.start();
-            }
-        }, playCompletionCallback);
-
-        LinearLayout menuLayout = findViewById(R.id.menuLinearLayout);
-        if (ViewUtil.isVisible(menuLayout)) {
-            loadTest(menuLayout);
-        }
-    }
-
-    //点击完成
-    public void onClickCommit(View view) {
-        showProgress(false);
-        CacheImageUtil.cacheAndLoadImg(ViewUtil.getNetImgByName("sheep_logo_3"), new Action1<File>() {
-            @Override
-            public void call(final File file) {
-                Observable.create(new ObservableOnSubscribe<String>() {
-                    @Override
-                    public void subscribe(ObservableEmitter<String> emitter) throws Exception {
-                        String srcFilPath = data.getFilePath();
-                        String outputFilename = String.format(Locale.CHINA, "%s_%d_%f.mp4", srcFilPath.substring(0, srcFilPath.lastIndexOf(".")), mCurrentConfig.hashCode(), mIntensity);
-                        Bitmap bmp = BitmapFactory.decodeFile(file.getAbsolutePath());
-                        //left 30px top 60px width 750
-                        Bitmap logo = BitmapUtil.createBigLogo(bmp, new Size().setWidth(G.WIDTH).setHeight(G.HEIGHT).setX(G.WIDTH * 30 / 750).setY(G.WIDTH * 60 / 750));
-                        bmp.recycle();
-                        CGEFFmpegNativeLibrary.generateVideoWithFilter(outputFilename, srcFilPath, mCurrentConfig, mIntensity, logo, CGENativeLibrary.TextureBlendMode.CGE_BLEND_ADDREV, 1.0f, false);
-
-                        LogUtil.println(ActEditVideo.class.getSimpleName(), "Done! The file is generated at: " + outputFilename);
-                        emitter.onNext(outputFilename);
-                    }
-                }).subscribeOn(Schedulers.io())
-                        .observeOn(AndroidSchedulers.mainThread())
-                        .subscribe(new AbsObserver<String>() {
-                            @Override
-                            public void onNext(String filePath) {
-                                sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));
-                                data.setFilePath(filePath);
-                                EventBus.getDefault().post(data);
-                                ActEditVideo.this.finish();
-                            }
-
-                            @Override
-                            public void onError(Throwable e) {
-                                G.showToast(e.getMessage());
-                            }
-
-                            @Override
-                            public void onComplete() {
-                                hideProgress();
-                            }
-                        });
-            }
-        });
-    }
-
-    //设置滤镜
-    @Override
-    public void setFilter(IFilter filter) {
-        if (mPlayerView != null && filter != null && filter.getConfig() != null) {
-            mCurrentConfig = filter.getConfig();
-            mPlayerView.setFilterWithConfig(mCurrentConfig);
-        }
-    }
-
-    @Override
-    public void setFilterIntensity(float intensity) {
-        if (mPlayerView != null) {
-            mIntensity = intensity;
-            mPlayerView.setFilterIntensity(mIntensity);
-        }
-    }
-
-    //下面为测试代码
-
-    private void loadTest(LinearLayout menuLayout) {
-
-        mShapeBtn = findViewById(R.id.switchShapeBtn);
-
-        mShapeBtn.setOnClickListener(new View.OnClickListener() {
-
-            private boolean useMask = false;
-            Bitmap bmp;
-
-            @Override
-            public void onClick(View v) {
-                useMask = !useMask;
-                if (useMask) {
-                    if (bmp == null)
-                        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
-
-                    if (bmp != null) {
-                        mPlayerView.setMaskBitmap(bmp, false, new VideoPlayerGLSurfaceView.SetMaskBitmapCallback() {
-                            @Override
-                            public void setMaskOK(CGEFrameRenderer renderer) {
-//                                if(mPlayerView.isUsingMask()) {
-//                                    renderer.setMaskFlipScale(1.0f, -1.0f);
-//                                }
-                                Log.i(Common.LOG_TAG, "enable mask!");
-                            }
-                        });
-                    }
-                } else {
-                    mPlayerView.setMaskBitmap(null, false);
-                }
-
-            }
-        });
-
-        mTakeshotBtn = findViewById(R.id.takeShotBtn);
-
-        mTakeshotBtn.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mPlayerView.takeShot(new VideoPlayerGLSurfaceView.TakeShotCallback() {
-                    @Override
-                    public void takeShotOK(Bitmap bmp) {
-                        if (bmp != null) {
-                            String s = ImageUtil.saveBitmap(bmp);
-                            ActEditVideo.this.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + s)));
-                        } else {
-                            Log.e(Common.LOG_TAG, "take shot failed!");
-                        }
-                    }
-                });
-            }
-        });
-
-
-        {
-            Button btn = new Button(this);
-            menuLayout.addView(btn);
-            btn.setAllCaps(false);
-            btn.setText("Last Recorded Video");
-            btn.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-
-                    Uri lastVideoUri = Uri.parse(data.getFilePath());
-                    mPlayerView.setVideoUri(lastVideoUri, new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
-                        @Override
-                        public void playPrepared(MediaPlayer player) {
-                            Log.i(Common.LOG_TAG, "The video is prepared to play");
-                            player.start();
-                        }
-                    }, playCompletionCallback);
-                }
-            });
-        }
-
-        String[] filePaths = {
-                data.getFilePath(),
-                "http://wge.wysaid.org/res/video/1.mp4",
-                "http://wysaid.org/p/test.mp4",
-        };
-
-        for (int i = 0; i != filePaths.length; ++i) {
-            MyVideoButton btn = new MyVideoButton(this);
-            btn.setText("Video" + i);
-            btn.videoUri = Uri.parse(filePaths[i]);
-            btn.videoView = mPlayerView;
-            btn.setOnClickListener(btn);
-            menuLayout.addView(btn);
-        }
-
-        mGalleryBtn = findViewById(R.id.galleryBtn);
-        mGalleryBtn.setOnClickListener(galleryBtnClickListener);
-
-        Button fitViewBtn = findViewById(R.id.fitViewBtn);
-        fitViewBtn.setOnClickListener(new View.OnClickListener() {
-            boolean shouldFit = false;
-
-            @Override
-            public void onClick(View v) {
-                shouldFit = !shouldFit;
-                mPlayerView.setFitFullView(shouldFit);
-            }
-        });
-
-        seekBarLl = findViewById(R.id.seekBarLl);
-        for (int i = 0; i < 6; i++) {
-            SeekBar sb = new SeekBar(SheepApp.getInstance());
-            sb.setMax(100);
-            sb.setProgress(50);
-            seekBarLl.addView(sb);
-            final int finalI = i;
-            sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-                @Override
-                public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
-                    onSeek(finalI, progress);
-                }
-
-                @Override
-                public void onStartTrackingTouch(SeekBar seekBar) {
-
-                }
-
-                @Override
-                public void onStopTrackingTouch(SeekBar seekBar) {
-
-                }
-            });
-        }
-    }
-
-    Button mShapeBtn;
-    Button mTakeshotBtn;
-    Button mGalleryBtn;
-    LinearLayout seekBarLl;
-
-    class MyVideoButton extends AppCompatButton implements View.OnClickListener {
-
-        Uri videoUri;
-        VideoPlayerGLSurfaceView videoView;
-
-        public MyVideoButton(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void onClick(View v) {
-
-            G.showToast("loading video: " + videoUri.getHost() + videoUri.getPath() + " If the video is from the internet, you may wait a while...");
-
-            videoView.setVideoUri(videoUri, new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
-                @Override
-                public void playPrepared(MediaPlayer player) {
-                    mPlayerView.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            G.showToast("Start playing " + videoUri.getHost() + videoUri.getPath());
-                        }
-                    });
-
-                    player.start();
-                }
-            }, playCompletionCallback);
-        }
-    }
-
-    private int[] progresses = {50, 50, 50, 50, 50, 50};
-
-    private float getPercent(int index) {
-        return (progresses[index] - 50) / 50.0f;
-    }
-
-    private int getPercent(int index, int max) {
-        return progresses[index] * max / 100;
-    }
-
-    private void onSeekHsv(int index, int progress) {
-        progresses[index] = progress;//色调(H),饱和度(S),明度(V)
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust hsv %.2f %.2f %.2f %.2f %.2f %.2f", getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i)));
-    }
-
-    private void onSeekHsl(int index, int progress) {
-        progresses[index] = progress;//0,0,0 色相(H)、饱和度(S)、明度(L)
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust hsl %.2f %.2f %.2f", getPercent(i++), getPercent(i++), getPercent(i)));
-    }
-
-    private void onSeekRgb(int index, int progress) {
-        progresses[index] = progress;//0,0,255,255 黑<白、反光<亮度
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@curve RGB(%d, %d)(%d, %d)", getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i, 255)));
-    }
-
-    private void onSeekLevel(int index, int progress) {
-        progresses[index] = progress;//0,1,1
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust level %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i)));
-    }
-
-    private void onSeekSaturation(int index, int progress) {
-        progresses[index] = progress;//1 饱和度
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust saturation %.2f ", getPercent(0)));
-    }
-
-    private void onSeek/*ColorBalance*/(int index, int progress) {
-        progresses[index] = progress;//0,0,0 红绿蓝
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust colorbalance %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i)));
-    }
-
-    private void onSeekHaze(int index, int progress) {
-        progresses[index] = progress;
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@style haze %.2f %.2f %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i)));
-    }
-
-    private static String[] TYPES = {"overlay", "colordodge", "pinlight", "ol", "screen"};
-
-    private void onSeekPixBlend(int index, int progress) {
-        progresses[index] = progress;
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust saturation %.2f @pixblend %s %.2f %.2f %.2f %d ", getPercent(i++), TYPES[progresses[1] / 20 % TYPES.length], getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i, 40)));
-    }
-
-    private void onSeekCurve(int index, int progress) {
-        progresses[index] = progress;
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@curve R(%d, %d)(%d, %d)(%d, %d) ", getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255)));
-    }
-
-    private void onSeekBeautify(int index, int progress) {
-        progresses[index] = progress;
-        int i = 0;
-        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@beautify face %d %d, %d ", getPercent(i++, 2), getPercent(i++, 1000), getPercent(i++, 1000)));
-    }
-
-    android.view.View.OnClickListener galleryBtnClickListener = new android.view.View.OnClickListener() {
-
-        @Override
-        public void onClick(final android.view.View view) {
-            Intent videoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
-            videoPickerIntent.setType("video/*");
-            startActivityForResult(videoPickerIntent, REQUEST_CODE_PICK_VIDEO);
-        }
-    };
-
-    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
-        switch (requestCode) {
-            case REQUEST_CODE_PICK_VIDEO:
-                if (resultCode == RESULT_OK) {
-
-                    mPlayerView.setVideoUri(data.getData(), new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
-                        @Override
-                        public void playPrepared(MediaPlayer player) {
-                            Log.i(Common.LOG_TAG, "The video is prepared to play");
-                            player.start();
-                        }
-                    }, playCompletionCallback);
-                }
-            default:
-                break;
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        Log.i(VideoPlayerGLSurfaceView.LOG_TAG, "activity onPause...");
-        mPlayerView.release();
-        mPlayerView.onPause();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-
-        mPlayerView.onResume();
-    }
-
-    @Override
-    protected Fragment initFragment() {
-        return new FgtChooseEditList();
-    }
-}

+ 43 - 20
app/src/main/java/com/sheep/gamegroup/module/find/activity/ActMediaChoose.java

@@ -8,19 +8,29 @@ import android.support.design.widget.TabLayout;
 import android.support.v4.view.ViewPager;
 import android.view.View;
 
+import com.alibaba.fastjson.JSONObject;
+import com.kfzs.cfyl.share_library.util.CallBackAPI;
+import com.kfzs.cfyl.share_library.util.Constant;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.IRefresh;
+import com.sheep.gamegroup.model.entity.DiscoveryTopic;
+import com.sheep.gamegroup.model.entity.Video;
 import com.sheep.gamegroup.module.find.fragment.FgtMediaPickerImg;
 import com.sheep.gamegroup.module.find.fragment.FgtMediaPickerVideo;
-import com.sheep.gamegroup.model.entity.Video;
 import com.sheep.gamegroup.util.CommonUtil;
+import com.sheep.gamegroup.util.DataUtil;
+import com.sheep.gamegroup.util.ListUtil;
 import com.sheep.gamegroup.util.TestUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.view.adapter.TitleFragmentListAdapter;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
 
-import org.greenrobot.eventbus.Subscribe;
+import org.afinal.simplecache.ApiKey;
+import org.greenrobot.eventbus.EventBus;
+
+import java.io.Serializable;
+import java.util.List;
 
 import butterknife.BindView;
 import cn.finalteam.rxgalleryfinal.api.CameraCallBack;
@@ -46,6 +56,7 @@ public class ActMediaChoose extends BaseActivity {
     ViewPager viewPager;
 
     private TitleFragmentListAdapter mAdapter;
+
     @Override
     public void initView() {
         TitleBarUtils.getInstance()
@@ -63,7 +74,7 @@ public class ActMediaChoose extends BaseActivity {
 
         mAdapter = new TitleFragmentListAdapter(getSupportFragmentManager());
         mAdapter.add(new FgtMediaPickerVideo(), "视频");
-        if(TestUtil.isDev()) {
+        if (TestUtil.isDev()) {
             mAdapter.add(new FgtMediaPickerImg(), "图片");
         }
         viewPager.setAdapter(mAdapter);
@@ -71,7 +82,7 @@ public class ActMediaChoose extends BaseActivity {
         viewPager.setCurrentItem(0);
         viewPager.setOffscreenPageLimit(mAdapter.getCount());
         CommonUtil.getInstance().reflex(indicator, this);
-        if(mAdapter.getCount() < 2){
+        if (mAdapter.getCount() < 2) {
             ViewUtil.setVisibility(indicator, false);
             ViewUtil.setVisibility(below_tab_line, false);
         }
@@ -90,42 +101,54 @@ public class ActMediaChoose extends BaseActivity {
     }
 
     @Override
-    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        if(resultCode == Activity.RESULT_OK){
+    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent intent) {
+        super.onActivityResult(requestCode, resultCode, intent);
+        if (resultCode == Activity.RESULT_OK) {
+            if (intent != null) {
+                switch (requestCode) {
+                    case Constant.MEDIA_ACTION_CUT_VIDEO:
+                        Serializable data = intent.getSerializableExtra(Video.class.getSimpleName());
+                        if (data != null) {
+                            CallBackAPI.get().goEditVideo(this, data);
+                        }
+                        return;
+                    case Constant.MEDIA_ACTION_EDIT_VIDEO:
+                        Serializable data1 = intent.getSerializableExtra(Video.class.getSimpleName());
+                        Video video = JSONObject.parseObject(JSONObject.toJSONString(data1), Video.class);
+                        if (video.getTopicIndex() >= 0) {
+                            List<DiscoveryTopic> discoveryTopicList = DataUtil.getInstance().getCacheList(ApiKey.getVideoTopic, DiscoveryTopic.class);
+                            DiscoveryTopic item = ListUtil.getItem(discoveryTopicList, video.getTopicIndex());
+                            if (item != null)
+                                video.setTopicId(item.getId());
+                        }
+                        EventBus.getDefault().post(video);
+                        finish();
+                        return;
+                }
+            }
             MediaUtils.onActivityResult(this, requestCode, null, new CameraCallBack() {
                 @Override
                 public void onGetImageSuccess(String cropFilePath) {
-                    if(mAdapter.getItem(1) instanceof IRefresh){
+                    if (mAdapter.getItem(1) instanceof IRefresh) {
                         ((IRefresh) mAdapter.getItem(1)).refreshData();
                     }
                 }
 
                 @Override
                 public void onGetVideoSuccess() {
-                    if(mAdapter.getItem(0) instanceof IRefresh){
+                    if (mAdapter.getItem(0) instanceof IRefresh) {
                         ((IRefresh) mAdapter.getItem(0)).refreshData();
                     }
                 }
 
                 @Override
                 public void onCropImageSuccess() {
-                    if(mAdapter.getItem(1) instanceof IRefresh){
+                    if (mAdapter.getItem(1) instanceof IRefresh) {
                         ((IRefresh) mAdapter.getItem(1)).refreshData();
                     }
                 }
             });
         }
     }
-    @Override
-    protected boolean needRegisterEventBus() {
-        return true;
-    }
 
-    @Subscribe
-    public void onEventMainThread(Video data) {
-        if(data != null){
-            finish();
-        }
-    }
 }

+ 1 - 1
app/src/main/java/com/sheep/gamegroup/module/find/fragment/FgtMediaPickerVideo.java

@@ -83,7 +83,7 @@ public class FgtMediaPickerVideo extends BaseListFragment6<MediaBean> {
             public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                 MediaBean item = ListUtil.getItem(apiRefresh.getList(), position);
                 if (item != null)
-                    Jump2View.getInstance().goActCutVideo(Video.from(item));
+                    Jump2View.getInstance().goActCutVideo(activity, Video.from(item));
             }
         });
 

+ 127 - 0
app/src/main/java/com/sheep/gamegroup/module/plugin/module/ClientPackage.java

@@ -0,0 +1,127 @@
+package com.sheep.gamegroup.module.plugin.module;
+
+/**
+ * Created by realicing on 2018/12/10.
+ * realicing@sina.com
+ * <p>
+ * dowload_url:	string
+ * 下载地址
+ * package_name:	string
+ * 包名
+ * created_at:	integer ($int64)
+ * 创建时间
+ * md_5:	string
+ * md5值
+ * status:	integer ($int32)
+ * 状态 1:发布 2:未发布
+ * platform:	integer ($int32)
+ * 平台 1:安卓 2:ios
+ * updated_at:	integer ($int64)
+ * 更新时间
+ * version:	string
+ * 包版本号
+ * Type:	string
+ * 文件类型标签,后台自定义
+ * id:	integer ($int64)
+ */
+public class ClientPackage {
+    private String Type;
+
+    private int created_at;
+
+    private String dowload_url;
+
+    private int id;
+
+    private String md_5;
+
+    private String package_name;
+
+    private int platform;
+
+    private int status;
+
+    private int updated_at;
+
+    private String version;
+
+    public String getType() {
+        return Type;
+    }
+
+    public void setType(String type) {
+        Type = type;
+    }
+
+    public int getCreated_at() {
+        return created_at;
+    }
+
+    public void setCreated_at(int created_at) {
+        this.created_at = created_at;
+    }
+
+    public String getDowload_url() {
+        return dowload_url;
+    }
+
+    public void setDowload_url(String dowload_url) {
+        this.dowload_url = dowload_url;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getMd_5() {
+        return md_5;
+    }
+
+    public void setMd_5(String md_5) {
+        this.md_5 = md_5;
+    }
+
+    public String getPackage_name() {
+        return package_name;
+    }
+
+    public void setPackage_name(String package_name) {
+        this.package_name = package_name;
+    }
+
+    public int getPlatform() {
+        return platform;
+    }
+
+    public void setPlatform(int platform) {
+        this.platform = platform;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public int getUpdated_at() {
+        return updated_at;
+    }
+
+    public void setUpdated_at(int updated_at) {
+        this.updated_at = updated_at;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+}

+ 18 - 0
app/src/main/java/com/sheep/gamegroup/module/plugin/module/Plugin.java

@@ -0,0 +1,18 @@
+package com.sheep.gamegroup.module.plugin.module;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public enum  Plugin {
+    media("com.kfzs.cfyl.media");
+    private final String packageName;
+
+    Plugin(String packageName) {
+        this.packageName = packageName;
+    }
+
+    public String getPackageName() {
+        return packageName;
+    }
+}

+ 166 - 0
app/src/main/java/com/sheep/gamegroup/module/plugin/util/PluginUtil.java

@@ -0,0 +1,166 @@
+package com.sheep.gamegroup.module.plugin.util;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import com.alibaba.fastjson.JSONObject;
+import com.didi.virtualapk.PluginManager;
+import com.sheep.gamegroup.model.entity.BaseMessage;
+import com.sheep.gamegroup.model.util.SheepSubscriber;
+import com.sheep.gamegroup.module.plugin.module.ClientPackage;
+import com.sheep.gamegroup.module.plugin.module.Plugin;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.Md5Util;
+import com.sheep.gamegroup.util.TestUtil;
+import com.sheep.jiuyan.samllsheep.BuildConfig;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.G;
+import com.zhy.http.okhttp.OkHttpUtils;
+import com.zhy.http.okhttp.callback.FileCallBack;
+
+import org.afinal.simplecache.ApiKey;
+
+import java.io.File;
+import java.util.Locale;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+import okhttp3.Call;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class PluginUtil {
+
+//    public static final String[] ABIS = { "armeabi-v7a", "arm64-v8a", "x86", "mips", "x86_64", "armeabi"};
+    public static final String[] ABIS = { "armeabi-v7a", "arm64-v8a", "x86"};
+    public static Observable<Plugin> startPlugin(Plugin plugin) {
+        return Observable.create((ObservableOnSubscribe<Plugin>) emitter -> {
+            if(TextUtils.equals(getCPU_ABI(), "x86")){
+                emitter.onError(new Throwable("暂不支持该设备"));
+                return;
+            }
+            if (PluginManager.getInstance(SheepApp.getInstance()).getLoadedPlugin(plugin.getPackageName()) == null) {
+//                String cpuAbi = getCPU_ABI();
+//                String pluginPath = String.format(Locale.CHINA, "%s/media_%s.apk", ClassFileHelper.DIR, cpuAbi);
+////                String pluginPath = ClassFileHelper.DIR + "/app-release.apk";
+//                LogUtil.println(PluginUtil.class.getSimpleName(), "CPU_ABI =", cpuAbi, "pluginPath =", pluginPath);
+//                File file = new File(pluginPath);
+                File pluginFile = getFile(plugin);
+                if(!pluginFile.exists()){
+                    emitter.onError(new Throwable("更新数据中,请稍候"));
+                    return;
+                }
+                try {
+                    PluginManager.getInstance(SheepApp.getInstance()).loadPlugin(pluginFile);
+                    emitter.onNext(plugin);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    emitter.onError(e);
+                }
+            } else {
+                emitter.onNext(plugin);
+            }
+        }).subscribeOn(Schedulers.io());
+    }
+
+    /**
+     * 根据系统的cpu_abi来获取最接近的cpu_abi
+     * @return
+     */
+    public static String getCPU_ABI() {
+        String CPU_ABI = android.os.Build.CPU_ABI;
+        if(!ListUtil.contains(ABIS, CPU_ABI)){
+            LogUtil.println(PluginUtil.class.getSimpleName(), "not contains", CPU_ABI);
+            CPU_ABI = ABIS[0];
+        }
+        return CPU_ABI;
+//        return "x86";
+    }
+
+
+    //初始化插件
+    public static  void initPlugin() {
+        Plugin plugin = Plugin.media;
+        String packageName = plugin.getPackageName();
+        String type = PluginUtil.getCPU_ABI();
+        int versionCode = BuildConfig.VERSION_CODE;
+        SheepApp.getInstance().getNetComponent().getApiService().getPackageVersion(packageName, type, versionCode)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new SheepSubscriber<BaseMessage>(SheepApp.getInstance()) {
+                    @Override
+                    public void onNext(BaseMessage baseMessage) {
+                        LogUtil.println("initPlugin", JSONObject.toJSONString(baseMessage.getData()));
+                        ClientPackage result = baseMessage.getData(ClientPackage.class);
+                        if(result != null && result.getMd_5() != null){
+                            String key = ApiKey.getPackageVersion(packageName, type, versionCode);
+                            File file = getFile(key);
+                            if(file.exists()){
+                                if(Md5Util.checkMD5(result.getMd_5(), file)){
+                                    return;
+                                }
+                            }
+                            downloadPlugin(result.getDowload_url(), getFileName(plugin));
+                        }
+//                        boolean isNewData = DataUtil.getInstance().isNewData(key);
+//                        if(isNewData){
+//
+//                        }
+                    }
+
+                    @Override
+                    public void onError(BaseMessage baseMessage) {
+                        if(TestUtil.isDev()) G.showToast(baseMessage);
+                    }
+                });
+    }
+
+    private static void downloadPlugin(String dowload_url, String fileName) {
+        OkHttpUtils.get().url(dowload_url).build().execute(new FileCallBack(getDirPath(), fileName) {
+            @Override
+            public void inProgress(float progress, long total, int id) {
+                LogUtil.println("downloadPlugin", dowload_url, String.format(Locale.CHINA, "%d%%", Math.round(progress * 100)));
+            }
+
+            @Override
+            public void onError(Call call, Exception e, int id) {
+                LogUtil.println("downloadPlugin", dowload_url, "下载失败");
+            }
+
+            @Override
+            public void onResponse(File response, int id) {
+                LogUtil.println("downloadPlugin", dowload_url, "下载完成");
+            }
+        });
+    }
+
+    public static File getDir() {
+        return SheepApp.getInstance().getDir("plugin", Context.MODE_PRIVATE);
+    }
+
+    public static String getDirPath() {
+        return SheepApp.getInstance().getDir("plugin", Context.MODE_PRIVATE).getPath();
+    }
+    public static File getFile(Plugin plugin) {
+        String packageName = plugin.getPackageName();
+        String type = PluginUtil.getCPU_ABI();
+        int versionCode = BuildConfig.VERSION_CODE;
+        String key = ApiKey.getPackageVersion(packageName, type, versionCode);
+        return getFile(key);
+    }
+    public static String getFileName(Plugin plugin) {
+        String packageName = plugin.getPackageName();
+        String type = PluginUtil.getCPU_ABI();
+        int versionCode = BuildConfig.VERSION_CODE;
+        String key = ApiKey.getPackageVersion(packageName, type, versionCode);
+        return key.hashCode()+".apk";
+    }
+    public static File getFile(String key) {
+        return new File(getDir(), key.hashCode()+".apk");
+    }
+}

+ 1 - 1
app/src/main/java/com/sheep/gamegroup/util/ConnectAddress.java

@@ -92,7 +92,7 @@ public enum ConnectAddress {
 
         @Override
         public String getAppUrl() {
-            return "http://ss.kfzs.com/";
+            return "http://ss.17xmy.com/";
         }
 
         @Override

+ 40 - 18
app/src/main/java/com/sheep/gamegroup/util/Jump2View.java

@@ -13,10 +13,11 @@ import android.view.Gravity;
 import android.view.View;
 
 import com.danikula.videocache.HttpProxyCacheServer;
+import com.kfzs.cfyl.share_library.util.CallBackAPI;
+import com.sheep.gamegroup.absBase.AbsObserver;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.IHomePageSearch;
 import com.sheep.gamegroup.absBase.IJumpWeb;
-import com.sheep.gamegroup.module.find.activity.ActMediaChoose;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
 import com.sheep.gamegroup.model.entity.Advertising;
 import com.sheep.gamegroup.model.entity.Agreement;
@@ -29,6 +30,8 @@ import com.sheep.gamegroup.model.entity.Container;
 import com.sheep.gamegroup.model.entity.CreditCard;
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.DialogEntity;
+import com.sheep.gamegroup.model.entity.DiscoveryTopic;
+import com.sheep.gamegroup.model.entity.DiscoveryVideo;
 import com.sheep.gamegroup.model.entity.GameListTag;
 import com.sheep.gamegroup.model.entity.GameListType;
 import com.sheep.gamegroup.model.entity.HomeListEntity;
@@ -45,7 +48,11 @@ import com.sheep.gamegroup.model.entity.Video;
 import com.sheep.gamegroup.model.entity.WebviewEntity;
 import com.sheep.gamegroup.model.entity.XianWanEntity;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
+import com.sheep.gamegroup.module.find.activity.ActMediaChoose;
 import com.sheep.gamegroup.module.login.ChangePasswordAct;
+import com.sheep.gamegroup.module.login.LoginAct;
+import com.sheep.gamegroup.module.plugin.module.Plugin;
+import com.sheep.gamegroup.module.plugin.util.PluginUtil;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
 import com.sheep.gamegroup.view.activity.ActApprenticeRedPacket;
 import com.sheep.gamegroup.view.activity.ActArticleComment;
@@ -55,9 +62,7 @@ import com.sheep.gamegroup.view.activity.ActCoinCenter;
 import com.sheep.gamegroup.view.activity.ActCommentGameApp;
 import com.sheep.gamegroup.view.activity.ActCreditCardTaskList;
 import com.sheep.gamegroup.view.activity.ActCreditCardWeb;
-import com.sheep.gamegroup.view.activity.ActCutVideo;
 import com.sheep.gamegroup.view.activity.ActDownloadWelfareList;
-import com.sheep.gamegroup.module.find.activity.ActEditVideo;
 import com.sheep.gamegroup.view.activity.ActEntertainmentLuckDraw;
 import com.sheep.gamegroup.view.activity.ActEveryDayShare;
 import com.sheep.gamegroup.view.activity.ActExchangeCMCC;
@@ -89,7 +94,6 @@ import com.sheep.gamegroup.view.activity.ActPlayGameList;
 import com.sheep.gamegroup.view.activity.ActPlayGameRecommendList;
 import com.sheep.gamegroup.view.activity.ActPlayGameUserLikeList;
 import com.sheep.gamegroup.view.activity.ActPlayVideo;
-import com.sheep.gamegroup.view.activity.ActVideoDetail;
 import com.sheep.gamegroup.view.activity.ActPublishArticle;
 import com.sheep.gamegroup.view.activity.ActReservation;
 import com.sheep.gamegroup.view.activity.ActSearchApp;
@@ -105,6 +109,7 @@ import com.sheep.gamegroup.view.activity.ActUserCommentDetail;
 import com.sheep.gamegroup.view.activity.ActUserLabelList;
 import com.sheep.gamegroup.view.activity.ActUserNoviceGuidance;
 import com.sheep.gamegroup.view.activity.ActVideoComment;
+import com.sheep.gamegroup.view.activity.ActVideoDetail;
 import com.sheep.gamegroup.view.activity.ActWebX5;
 import com.sheep.gamegroup.view.activity.ActXianWanWeb;
 import com.sheep.gamegroup.view.activity.ActXiaomiGame;
@@ -119,7 +124,6 @@ import com.sheep.gamegroup.view.activity.FeedbackAct;
 import com.sheep.gamegroup.view.activity.GameTaskOrderListAct;
 import com.sheep.gamegroup.view.activity.GamemakeMoneyAct;
 import com.sheep.gamegroup.view.activity.LieMakeMoneyAct;
-import com.sheep.gamegroup.module.login.LoginAct;
 import com.sheep.gamegroup.view.activity.PersonalCenterAct;
 import com.sheep.gamegroup.view.activity.PersonalInfoAct;
 import com.sheep.gamegroup.view.activity.RealNameAuthenAct;
@@ -162,7 +166,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
+import io.reactivex.ObservableSource;
 import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.functions.Function;
 import io.reactivex.schedulers.Schedulers;
 import me.iwf.photopicker.PhotoPicker;
 import me.iwf.photopicker.PhotoPreview;
@@ -2272,29 +2278,45 @@ public class Jump2View {
         Activity activity = ActivityManager.getInstance().currentActivity();
         activity.startActivity(DataUtil.putObject(new Intent(activity, ActVideoDetail.class), item));
     }
-
     /**
-     * 剪切视频
+     * 播放视频
      *
-     * @param data 视频数据,包括地址与时长,宽高等
+     * @param item 视频对象
      */
-    public void goActCutVideo(Video data) {
+    public void goActPlayVideoArticle(Serializable item, ArrayList<DiscoveryVideo> videoList) {
         Activity activity = ActivityManager.getInstance().currentActivity();
-        Intent intent = new Intent(activity, ActCutVideo.class);
-        DataUtil.putObject(intent, data);
-        activity.startActivity(intent);
+        Intent intent = new Intent(activity, ActVideoDetail.class);
+        intent.putExtra(ArrayList.class.getSimpleName(), videoList);
+        activity.startActivity(DataUtil.putObject(intent, item));
     }
 
     /**
-     * 编辑视频
+     * 剪切视频
      *
      * @param data 视频数据,包括地址与时长,宽高等
      */
-    public void goActEditVideo(Video data) {
-        Activity activity = ActivityManager.getInstance().currentActivity();
-        Intent intent = new Intent(activity, ActEditVideo.class);
-        DataUtil.putObject(intent, data);
-        activity.startActivity(intent);
+    public void goActCutVideo(Activity activity, Video data) {
+        PluginUtil.startPlugin(Plugin.media)
+                .flatMap((Function<Plugin, ObservableSource<BaseMessage>>) plugin -> SheepApp.getInstance().getNetComponent().getApiService().getVideoTopic())
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new AbsObserver<BaseMessage>() {
+                    @Override
+                    public void onNext(BaseMessage baseMessage) {
+                        List<DiscoveryTopic> discoveryTopicList = baseMessage.getDataList(DiscoveryTopic.class);
+                        ArrayList<String> stringList = new ArrayList<>();
+                        ListUtil.forEach(discoveryTopicList, discoveryTopic -> stringList.add(discoveryTopic.getTopic()));
+                        String videoPath = data.getFilePath();
+                        String path = String.format(Locale.CHINA, "%s_%d.png", videoPath.substring(0, videoPath.indexOf(".")), 0);
+                        LogUtil.println("videoUtil", path);
+                        CallBackAPI.get().goCutVideo(activity, data, stringList);
+                    }
+
+                    @Override
+                    public void onError(Throwable e) {
+                        G.showToast(e.getMessage());
+                    }
+                });
     }
 
     /**

+ 13 - 0
app/src/main/java/com/sheep/gamegroup/util/ListUtil.java

@@ -1,6 +1,8 @@
 package com.sheep.gamegroup.util;
 
 
+import android.text.TextUtils;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -223,6 +225,17 @@ public class ListUtil {
         if (allList != null && removeList != null)
             allList.removeAll(removeList);
     }
+
+    //是事包含指定字符串
+    public static boolean contains(String[] items, String src) {
+        for (String item : items) {
+            if(TextUtils.equals(item, src)){
+                return true;
+            }
+        }
+        return false;
+    }
+
     //I 传入的数据, R 返回的结果
     public static interface CallBack<I, R> {
         public R call(I i);

+ 27 - 13
app/src/main/java/com/sheep/gamegroup/util/MediaMetadataRetrieverUtil.java

@@ -6,6 +6,7 @@ import android.media.MediaMetadataRetriever;
 import android.net.Uri;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
+import android.view.View;
 import android.widget.ImageView;
 
 import com.chad.library.adapter.base.BaseQuickAdapter;
@@ -83,7 +84,28 @@ public class MediaMetadataRetrieverUtil {
     /**
      * 取出视频文件中的图片帧列表
      */
-    public void initRv(final RecyclerView recyclerView) {
+    public void initRv(final RecyclerView recyclerView, ArrayList<String> videoPathList) {
+        recyclerView.setLayoutManager(new GridLayoutManager(SheepApp.getInstance(), size));
+        BaseQuickAdapter<String, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_iv_mh, videoPathList) {
+            @Override
+            protected void convert(BaseViewHolder helper, String item) {
+                ImageView imageView = helper.getView(R.id.item_iv);
+                ViewUtil.setImagePath(imageView, item);
+            }
+        };
+        baseQuickAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+            @Override
+            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+                Jump2View.getInstance().showImgList(ActivityManager.getInstance().currentActivity(), position, videoPathList);
+            }
+        });
+        recyclerView.setAdapter(baseQuickAdapter);
+    }
+
+    /**
+     * 取出视频文件中的图片帧列表
+     */
+    public void initRv1(final RecyclerView recyclerView) {
         Observable.create(new ObservableOnSubscribe<List<Bitmap>>() {
             @Override
             public void subscribe(ObservableEmitter<List<Bitmap>> emitter) throws Exception {
@@ -108,6 +130,7 @@ public class MediaMetadataRetrieverUtil {
                 });
 
     }
+
     /**
      * 取出视频文件中的图片帧列表
      */
@@ -123,16 +146,7 @@ public class MediaMetadataRetrieverUtil {
                 .subscribe(new AbsObserver<List<String>>() {
                     @Override
                     public void onNext(final List<String> strings) {
-                        recyclerView.setLayoutManager(new GridLayoutManager(SheepApp.getInstance(), size));
-                        BaseQuickAdapter<String, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_iv_mh, strings) {
-                            @Override
-                            protected void convert(BaseViewHolder helper, String item) {
-                                ImageView imageView = helper.getView(R.id.item_iv);
-                                ViewUtil.setImagePath(imageView, item);
-                                Jump2View.getInstance().showImgList(ActivityManager.getInstance().currentActivity(), helper.getAdapterPosition(), (ArrayList<String>) strings);
-                            }
-                        };
-                        recyclerView.setAdapter(baseQuickAdapter);
+                        initRv(recyclerView, (ArrayList<String>) strings);
                     }
                 });
 
@@ -176,7 +190,7 @@ public class MediaMetadataRetrieverUtil {
             long curTime = System.currentTimeMillis();
             LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000, (curTime - time) / 10000);
             return resultList;
-        }catch (Exception e){
+        } catch (Exception e) {
             e.printStackTrace();
             LogUtil.println(MediaMetadataRetrieverUtil.class.getSimpleName(), "getFrameBitmapList", e.getMessage());
         }
@@ -223,7 +237,7 @@ public class MediaMetadataRetrieverUtil {
                         e.printStackTrace();
                     }
                 }
-                if(bitmap != null)
+                if (bitmap != null)
                     bitmap.recycle();
             }
         }

+ 2 - 72
app/src/main/java/com/sheep/gamegroup/util/TestUtil.java

@@ -69,7 +69,6 @@ import com.zhy.http.okhttp.OkHttpUtils;
 import com.zhy.http.okhttp.callback.FileCallBack;
 import com.zhy.http.okhttp.callback.StringCallback;
 
-import org.wysaid.nativePort.CGENativeLibrary;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -259,7 +258,7 @@ public class TestUtil {
      */
     public static void test(final Activity activity) {
         final String[] items = {"复制token", "添加token", "复制打点数据", "从jenkins下载小绵羊安装包", "测试表情包",
-                "游戏搜索", "测试bitmap", "根据原始图片生成滤镜图片", "剪切视频","编辑视频", "我的关注", "足迹",
+                "游戏搜索", "测试bitmap", "剪切视频", "我的关注", "足迹",
                 "测试联通卡", "测试联通卡2", "测试签名1", "测试签名2", "测试孔剑秋faq正式服",
                 "跳转QQ1", "跳转QQ2", "跳转QQ3", "跳转白白QQ", "龙猫竞猜", "龙猫竞猜-scheme",
                 "有米科技", "手机型号测试", "测试通知栏", "测试自定义通知栏", "测试自定义通知栏2",
@@ -281,15 +280,9 @@ public class TestUtil {
                             case "测试bitmap":
                                 testBitmap();
                                 break;
-                            case "根据原始图片生成滤镜图片":
-                                testCreateFilterbleImg(ViewUtil.getNetImgByName("alter_original"));
-                                break;
                             case "剪切视频":
                                 testCutVideo();
                                 break;
-                            case "编辑视频":
-                                testEditVideo();
-                                break;
                             case "足迹":
                                 Jump2View.getInstance().goActFootPrint();
                                 break;
@@ -632,50 +625,6 @@ public class TestUtil {
         ViewUtil.saveImage(result, ClassFileHelper.DIR, String.valueOf(System.currentTimeMillis()) + ".png");
     }
 
-    //根据原始图片生成滤镜图片
-    private static void testCreateFilterbleImg(String url) {
-        CacheImageUtil.cacheAndLoadImg(url, new Action1<File>() {
-            @Override
-            public void call(File file) {
-                Observable.just(file)
-                        .flatMap(new Function<File, ObservableSource<Bitmap>>() {
-                            @Override
-                            public ObservableSource<Bitmap> apply(File file) throws Exception {
-                                Bitmap src = BitmapFactory.decodeFile(file.getAbsolutePath());
-//                                ViewUtil.saveImage(src, ClassFileHelper.DIR, String.valueOf(System.currentTimeMillis()) + ".png");
-                                return Observable.just(src);
-                            }
-                        })
-                        .subscribeOn(Schedulers.io())
-                        .flatMap(new Function<Bitmap, Observable<Integer>>() {
-                            @Override
-                            public Observable<Integer> apply(final Bitmap src) throws Exception {
-                                List<IFilter> list = ColorBalanceFilter.getDefaultFilterList();
-                                ListUtil.forEach(list, new Action1<IFilter>() {
-                                    @Override
-                                    public void call(IFilter filter) {
-                                        Bitmap dstImage = CGENativeLibrary.filterImage_MultipleEffects(src, filter.getConfig(), 1.0f);
-                                        ViewUtil.saveImage(dstImage, ClassFileHelper.DIR, String.valueOf(System.currentTimeMillis()) + ".png");
-                                        dstImage.recycle();
-                                    }
-                                });
-                                src.recycle();
-                                return Observable.just(list.size());
-                            }
-                        })
-                        .subscribeOn(Schedulers.io())
-                        .observeOn(AndroidSchedulers.mainThread())
-                        .subscribe(new AbsObserver<Integer>() {
-                            @Override
-                            public void onNext(Integer integer) {
-                                G.showToast(String.valueOf(integer));
-                            }
-                        });
-            }
-        });
-
-    }
-
     private static void testCutVideo() {
         Observable.create(new ObservableOnSubscribe<MediaBean>() {
             @Override
@@ -690,26 +639,7 @@ public class TestUtil {
                 .subscribe(new AbsObserver<MediaBean>() {
                     @Override
                     public void onNext(MediaBean mediaBean) {
-                        Jump2View.getInstance().goActCutVideo(Video.from(mediaBean));
-                    }
-                });
-
-    }
-    private static void testEditVideo() {
-        Observable.create(new ObservableOnSubscribe<MediaBean>() {
-            @Override
-            public void subscribe(ObservableEmitter<MediaBean> emitter) throws Exception {
-                List<MediaBean> mediaBeanList = MediaUtils.getMediaWithVideoList(SheepApp.getInstance(), 1, 1);
-                MediaBean item = ListUtil.getItem(mediaBeanList, 0);
-                emitter.onNext(item);
-            }
-        })
-                .subscribeOn(Schedulers.io())
-                .observeOn(AndroidSchedulers.mainThread())
-                .subscribe(new AbsObserver<MediaBean>() {
-                    @Override
-                    public void onNext(MediaBean mediaBean) {
-                        Jump2View.getInstance().goActEditVideo(Video.from(mediaBean));
+                        Jump2View.getInstance().goActCutVideo(ActivityManager.getInstance().currentActivity(), Video.from(mediaBean));
                     }
                 });
 

+ 0 - 17
app/src/main/java/com/sheep/gamegroup/util/ViewUtil.java

@@ -62,7 +62,6 @@ import com.sheep.gamegroup.absBase.IContentTypeContainer;
 import com.sheep.gamegroup.absBase.ITag;
 import com.sheep.gamegroup.dateview.DatePickerDialog;
 import com.sheep.gamegroup.dateview.DateUtil;
-import com.sheep.gamegroup.module.find.util.IFilter;
 import com.sheep.gamegroup.model.entity.Advertising;
 import com.sheep.gamegroup.model.entity.Container;
 import com.sheep.gamegroup.model.entity.DialogConfig;
@@ -72,7 +71,6 @@ import com.sheep.gamegroup.model.entity.Lp;
 import com.sheep.gamegroup.model.entity.PayEntity;
 import com.sheep.gamegroup.model.entity.RobTask;
 import com.sheep.gamegroup.model.entity.TaskEty;
-import com.sheep.gamegroup.util.glide.FilterTransform;
 import com.sheep.gamegroup.util.glide.RoundedCornersTransformation;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
 import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
@@ -1580,21 +1578,6 @@ public class ViewUtil {
         }
     }
 
-    //加载默认原图滤镜效果
-    public static void setImage(ImageView imageView, final IFilter filter) {
-        if (imageView != null && filter != null && filter.getConfig() != null) {
-            String url = getNetImgByName("alter_original");
-            if (filter.getConfig().isEmpty()) {
-                setImage(imageView, url);
-                return;
-            }
-            Glide.with(SheepApp.getInstance())
-                    .load(url)
-                    .apply(new RequestOptions().transform(new FilterTransform(filter)))
-                    .into(imageView);
-        }
-    }
-
     public static void setImage(ImageView imageView, String pictures) {
         if (imageView != null) {
             if (TextUtils.isEmpty(pictures)) {

File diff suppressed because it is too large
+ 513 - 506
app/src/main/java/com/sheep/gamegroup/view/activity/ActCutVideo.java


+ 1 - 0
app/src/main/java/com/sheep/gamegroup/view/activity/ActMain.java

@@ -473,4 +473,5 @@ public class ActMain extends BaseActYmPermissionCheck {
             container.setT(null);
 
     }
+
 }

+ 103 - 106
app/src/main/java/com/sheep/gamegroup/view/activity/ActVideoDetail.java

@@ -2,6 +2,7 @@ package com.sheep.gamegroup.view.activity;
 
 import android.annotation.SuppressLint;
 import android.content.Context;
+import android.content.Intent;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.net.Uri;
@@ -29,6 +30,7 @@ import com.sheep.gamegroup.util.ActionUtil;
 import com.sheep.gamegroup.util.ApiUtil;
 import com.sheep.gamegroup.util.DataUtil;
 import com.sheep.gamegroup.util.Jump2View;
+import com.sheep.gamegroup.util.ListUtil;
 import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.gamegroup.util.TestUtil;
 import com.sheep.gamegroup.util.ViewUtil;
@@ -39,6 +41,9 @@ import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.umeng.socialize.bean.SHARE_MEDIA;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import butterknife.BindView;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.schedulers.Schedulers;
@@ -48,7 +53,7 @@ import io.reactivex.schedulers.Schedulers;
  * realicing@sina.com
  * 小绵羊3.4.5新增 -- 视频详情
  */
-public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfoListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, View.OnLayoutChangeListener {
+public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfoListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -93,23 +98,31 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
     private int user_id;
     private String video_url;
     private DiscoveryVideo newVideo;
-
+    private ArrayList<DiscoveryVideo> videoList;
+    private int position;
     @Override
     public void initView() {
-        initVolume();
-        DiscoveryVideo lastVideo = DataUtil.getObject(getIntent(), DiscoveryVideo.class);
+        Intent intent = getIntent();
+        videoList = (ArrayList<DiscoveryVideo>) intent.getSerializableExtra(ArrayList.class.getSimpleName());
+        DiscoveryVideo lastVideo = DataUtil.getObject(intent, DiscoveryVideo.class);
+        if(!ListUtil.isEmpty(videoList) && lastVideo != null)
+            position = videoList.indexOf(lastVideo);
         if (lastVideo == null) {
-            video_id = DataUtil.getObject(getIntent(), Integer.class);
+            video_id = DataUtil.getObject(intent, Integer.class);
             loadVideoData(null);
         } else {
-            video_id = lastVideo.getId();
-            user_id = lastVideo.getUser_id();
-            video_url = lastVideo.getResource();
-            loadVideoData(lastVideo);
+            initVideoData(lastVideo);
         }
         ViewUtil.setImage(video_camera_iv, ViewUtil.getNetImgByName("add_article_camera"));
     }
 
+    private void initVideoData(DiscoveryVideo lastVideo) {
+        video_id = lastVideo.getId();
+        user_id = lastVideo.getUser_id();
+        video_url = lastVideo.getResource();
+        loadVideoData(lastVideo);
+    }
+
     private void loadVideoData(DiscoveryVideo discoveryVideo) {
         if (discoveryVideo == null) {
             ViewUtil.setText(video_like_tv, ViewUtil.BLOCK);
@@ -135,7 +148,6 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
         videoView.setOnPreparedListener(this);
         videoView.setOnErrorListener(this);
         videoView.setOnCompletionListener(this);
-        videoView.addOnLayoutChangeListener(this);
 //        videoView.setMediaController(new MediaController(this));
         videoView.setVideoURI(uri);
     }
@@ -341,20 +353,19 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
     protected void onDestroy() {
         destroy();
         super.onDestroy();
-        mAudioManager = null;
     }
 
     //    //滑动方向
-//    private int direction = 0;
+    private int direction = 0;
 //    //左右滑动
-//    public static final int DIRECTION_LEFT_RIGHT = 1;
+    public static final int DIRECTION_LEFT_RIGHT = 1;
 //    //上下滑动
-//    public static final int DIRECTION_TOP_BOTTOM = 2;
+    public static final int DIRECTION_TOP_BOTTOM = 2;
     private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
         @Override
         public boolean onDown(MotionEvent e) {
             LogUtil.println("mGestureListener", "onDown");
-//            direction = 0;
+            direction = 0;
             return super.onDown(e);
         }
 
@@ -374,87 +385,84 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
 //            playOrPause();
             return super.onSingleTapConfirmed(e);
         }
-
         @Override
-        public boolean onScroll(MotionEvent e1, MotionEvent e2,
-                                float distanceX, float distanceY) {
-            float mOldX = e1.getX(), mOldY = e1.getY();
-            int y = (int) e2.getRawY();
-            int windowWidth = ActVideoDetail.this.windowWidth;
-            int windowHeight = ActVideoDetail.this.windowHeight;
-            int lineMiddle = windowWidth / 2;
-            if (mOldX > lineMiddle)// 左边滑动
-                onBrightnessSlide((mOldY - y) / windowHeight);
-            else if (mOldX < lineMiddle)// 右边滑动
-                onVolumeSlide((mOldY - y) / windowHeight);
-            return super.onScroll(e1, e2, distanceX, distanceY);
-        }
-
-    };
-    private AudioManager mAudioManager;
-    private int mMaxVolume;//最大音量
-    private int mVolume;//当前音量
-
-    private void initVolume() {
-        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
-        if (mAudioManager != null)
-            mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
-    }
-
-    //滑动改变音量
-    private void onVolumeSlide(float percent) {
-        if (mVolume == -1) {
-            mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
-            if (mVolume < 0)
-                mVolume = 0;
-
-            // 显示
-//                mOperationBg.setImageResource(R.drawable.video_volumn_bg);
-//                mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
+        public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
+            LogUtil.println("mGestureListener", distanceX, distanceY);
+            if (event1 == null || event2 == null) {
+                return super.onScroll(event1, event2, distanceX, distanceY);
+            }
+            if (direction == 0) {
+                float a = Math.abs(distanceY);
+                float b = Math.abs(distanceX);
+                if (a > b) {
+                    LogUtil.println("mGestureListener", "上下滑动");
+                    direction = DIRECTION_TOP_BOTTOM;
+                } else if (b > a) {
+                    LogUtil.println("mGestureListener", "左右滑动");
+                    direction = DIRECTION_LEFT_RIGHT;
+                }
+            }
+            return super.onScroll(event1, event2, distanceX, distanceY);
         }
 
-        int index = (int) (percent * mMaxVolume) + mVolume;
-        if (index > mMaxVolume)
-            index = mMaxVolume;
-        else if (index < 0)
-            index = 0;
-
-        // 变更声音
-        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
-        // 变更进度条
-//            ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
-//            lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume;
-//            mOperationPercent.setLayoutParams(lp);
-    }
-
-    private float mBrightness = -1;
-
-    //滑动改变亮度
-    private void onBrightnessSlide(float percent) {
-        if (mBrightness < 0) {
-            mBrightness = getWindow().getAttributes().screenBrightness;
-            if (mBrightness <= 0.00f)
-                mBrightness = 0.50f;
-            if (mBrightness < 0.01f)
-                mBrightness = 0.01f;
-
-            // 显示
-//                mOperationBg.setImageResource(R.drawable.video_brightness_bg);
-//                mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
+        @Override
+        public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
+            LogUtil.println("mGestureListener", velocityX, velocityY);
+            if (event1 == null || event2 == null) {
+                return super.onFling(event1, event2, velocityX, velocityY);
+            }
+            final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
+            if (event1.getX() - event2.getX() > FLING_MIN_DISTANCE
+                    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
+                // Fling left
+                LogUtil.println("mGestureListener", "Fling left", position);
+                position ++;
+                if(position == ListUtil.size(videoList))
+                    position = 0;
+                LogUtil.println("mGestureListener", "Fling left", position);
+                DiscoveryVideo item = ListUtil.getItem(videoList, position);
+                if(item != null) {
+                    initVideoData(item);
+                    Uri uri = Uri.parse(SheepApp.getHttpProxyCacheServer().getProxyUrl(video_url));
+                    videoView.stopPlayback();
+                    videoView.setVideoURI(uri);
+                    videoView.requestFocus();
+                }
+            } else if (event2.getX() - event1.getX() > FLING_MIN_DISTANCE
+                    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
+                // Fling right
+                LogUtil.println("mGestureListener", "Fling rigth", position);
+                if(position == 0)
+                    position = ListUtil.size(videoList);
+                else
+                    position --;
+                LogUtil.println("mGestureListener", "Fling rigth", position);
+                DiscoveryVideo item = ListUtil.getItem(videoList, position);
+                if(item != null) {
+                    initVideoData(item);
+                    Uri uri = Uri.parse(SheepApp.getHttpProxyCacheServer().getProxyUrl(video_url));
+                    videoView.stopPlayback();
+                    videoView.setVideoURI(uri);
+                    videoView.requestFocus();
+                }
+            } else if (event2.getY() - event1.getY() > FLING_MIN_DISTANCE
+                    && Math.abs(velocityY) > FLING_MIN_VELOCITY) {
+                if (direction == DIRECTION_LEFT_RIGHT) {
+                    // Fling down
+                    LogUtil.println("mGestureListener", "Fling down");
+                }
+            } else if (event1.getY() - event2.getY() > FLING_MIN_DISTANCE
+                    && Math.abs(velocityY) > FLING_MIN_VELOCITY) {
+                if (direction == DIRECTION_LEFT_RIGHT) {
+                    // Fling up
+                    LogUtil.println("mGestureListener", "Fling up");
+                }
+            }
+//            return super.onFling(event1, event2, velocityX, velocityY);
+            return false;
         }
-        WindowManager.LayoutParams lpa = getWindow().getAttributes();
-        lpa.screenBrightness = mBrightness + percent;
-        if (lpa.screenBrightness > 1.0f)
-            lpa.screenBrightness = 1.0f;
-        else if (lpa.screenBrightness < 0.01f)
-            lpa.screenBrightness = 0.01f;
-        getWindow().setAttributes(lpa);
-
-//            ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
-//            lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness);
-//            mOperationPercent.setLayoutParams(lp);
-    }
 
+    };
     @Override
     public boolean onInfo(MediaPlayer mediaPlayer, int what, int extra) {
         LogUtil.println("ActPlayVideo", "onInfo what = " + what + " extra = " + extra);
@@ -463,15 +471,13 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
         switch (what) {
             case MediaPlayer.MEDIA_INFO_BUFFERING_START:
                 LogUtil.println("ActPlayVideo", "onInfo", "正在缓冲");
-                if (video_loading != null)
-                    video_loading.setVisibility(View.VISIBLE);
+                ViewUtil.setVisibility(video_loading, true);
                 break;
             case MediaPlayer.MEDIA_INFO_BUFFERING_END:
             case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
                 LogUtil.println("ActPlayVideo", "onInfo", "缓冲完成");
                 //缓存完成,继续播放
-                if (video_loading != null)
-                    video_loading.setVisibility(View.GONE);
+                ViewUtil.setVisibility(video_loading, false);
                 break;
         }
         return false;
@@ -480,8 +486,8 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
     @Override
     public void onPrepared(MediaPlayer mediaPlayer) {
         LogUtil.println("ActPlayVideo", "onPrepared");
-        if (video_loading != null)
-            video_loading.setVisibility(View.GONE);
+        mediaPlayer.start();
+        ViewUtil.setVisibility(video_loading, false);
     }
 
     @Override
@@ -495,13 +501,4 @@ public class ActVideoDetail extends BaseUMActivity implements MediaPlayer.OnInfo
         LogUtil.println("ActPlayVideo", "onCompletion");
     }
 
-    private int windowWidth = G.WIDTH;
-    private int windowHeight = G.HEIGHT;
-
-    @Override
-    public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
-        LogUtil.println("ActPlayVideo", "onLayoutChange", left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
-        this.windowWidth = left + right;
-        this.windowHeight = top + bottom;
-    }
 }

+ 2 - 1
app/src/main/java/com/sheep/gamegroup/view/adapter/AdpVideo.java

@@ -17,6 +17,7 @@ import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 
@@ -46,7 +47,7 @@ public class AdpVideo extends RecyclerViewAdapter<DiscoveryVideo> {
         viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                Jump2View.getInstance().goActPlayVideoArticle(item);
+                Jump2View.getInstance().goActPlayVideoArticle(item, (ArrayList<DiscoveryVideo>) mDatas);
             }
         });
     }

+ 279 - 268
app/src/main/java/com/sheep/gamegroup/view/customview/VideoFramesView.java

@@ -1,268 +1,279 @@
-package com.sheep.gamegroup.view.customview;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.support.v7.widget.RecyclerView;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.RelativeLayout;
-
-import com.chad.library.adapter.base.BaseQuickAdapter;
-import com.chad.library.adapter.base.BaseViewHolder;
-import com.sheep.gamegroup.model.entity.Video;
-import com.sheep.gamegroup.util.LogUtil;
-import com.sheep.gamegroup.util.MediaMetadataRetrieverUtil;
-import com.sheep.jiuyan.samllsheep.R;
-
-import java.io.File;
-import java.util.Locale;
-
-import rx.functions.Action1;
-
-
-/**
- * Created by realicing on 2018/11/29.
- * realicing@sina.com
- * 显示本地视频文件对应的视频帧
- */
-public class VideoFramesView extends RelativeLayout {
-    public VideoFramesView(Context context) {
-        super(context);
-        initView();
-    }
-
-    public VideoFramesView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        initView();
-    }
-
-    public VideoFramesView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        initView();
-    }
-
-    private RecyclerView recyclerView;
-    private View line_start;
-    private View line_end;
-
-    private void initView() {
-        LayoutInflater.from(getContext()).inflate(R.layout.custom_video_frames_view, this, true);
-        recyclerView = findViewById(R.id.recyclerView);
-        line_start = findViewById(R.id.line_start);
-        line_end = findViewById(R.id.line_end);
-        line_start.setOnTouchListener(new OnTouchListener() {
-            private float lastEventX;
-
-            @SuppressLint("ClickableViewAccessibility")
-            @Override
-            public boolean onTouch(View view, MotionEvent event) {
-                float maxX = line_end.getX();
-                float minX = maxX - (firstEndX - firstStartX);//结束位置 - 可以设置的长度
-                switch (event.getAction()) {
-                    case MotionEvent.ACTION_DOWN:
-                        lastEventX = event.getX();
-                        break;
-                    case MotionEvent.ACTION_MOVE:
-                        float mx = Math.max(firstStartX, view.getX() + event.getX() - lastEventX);
-                        if (mx > maxX)
-                            mx = maxX;
-                        if (mx < minX) {
-                            maxX += mx - minX;
-                            line_end.setX(maxX);
-                            view.setX(mx);
-                        } else {
-                            view.setX(mx);
-                        }
-                        if (onTimeChangeListener != null) {
-                            onTimeChangeListener.call((maxX - mx) * video.getDuration() / (rvW - lineW));
-                        }
-                        break;
-                    case MotionEvent.ACTION_UP:
-                        break;
-                    case MotionEvent.ACTION_CANCEL:
-                        break;
-                }
-                view.invalidate();
-                return true;
-            }
-        });
-        line_end.setOnTouchListener(new OnTouchListener() {
-            private float lastEventX;
-
-            @SuppressLint("ClickableViewAccessibility")
-            @Override
-            public boolean onTouch(View view, MotionEvent event) {
-                float minX = line_start.getX();
-                float maxX = firstEndX - firstStartX + minX;
-                float endX = firstStartX + rvW - lineW;
-                switch (event.getAction()) {
-                    case MotionEvent.ACTION_DOWN:
-                        lastEventX = event.getX();
-                        break;
-                    case MotionEvent.ACTION_MOVE:
-                        float mx = Math.min(view.getX() + event.getX() - lastEventX, endX);
-                        if (mx < minX)
-                            mx = minX;
-                        if (mx > maxX) {
-                            minX += mx - maxX;
-                            line_start.setX(minX);
-                            view.setX(mx);
-                        } else {
-                            view.setX(mx);
-                        }
-                        if (onTimeChangeListener != null) {
-                            onTimeChangeListener.call((mx - minX) * video.getDuration() / (rvW - lineW));
-                        }
-                        break;
-                    case MotionEvent.ACTION_UP:
-                        break;
-                    case MotionEvent.ACTION_CANCEL:
-                        break;
-                }
-                view.invalidate();
-                return true;
-            }
-        });
-    }
-
-    //开头线的进度
-    public float getStartPercent() {
-        if (line_start != null && recyclerView != null) {
-            return (line_start.getX() - firstStartX) / (rvW - lineW);
-        }
-        return 0;
-    }
-
-    private float firstStartX;//初始时开头的x位置
-    private float firstEndX;//初始时结尾的x位置
-    private int lineW;//开头与结尾线的宽度
-    private int rvW;//图片列表的长度,减去lineW后==总进度的长度
-
-    //结尾线的进度
-    public float getEndPercent() {
-        if (line_end != null && recyclerView != null) {
-            return 1.0f - ((firstStartX + rvW - lineW - line_end.getX()) / (rvW - lineW));
-        }
-        return 0;
-    }
-
-    //总的进度
-    public float getPercent() {
-        if (line_end != null && recyclerView != null) {
-            return (line_end.getX() - line_start.getX()) / (rvW - lineW);
-        }
-        return 0;
-    }
-
-    public String getLineInfo() {
-        return String.format(Locale.CHINA, "firstStartX = %f, firstEndX = %f, startX = %f, endX = %f, lineW = %d, rvW = %d, startPercent = %f, endPercent = %f, percent = %f", firstStartX, firstEndX, line_start.getX(), line_end.getX(), line_end.getWidth(), recyclerView.getWidth(), getStartPercent(), getEndPercent(), getPercent());
-    }
-
-    private MediaMetadataRetrieverUtil mediaMetadataRetrieverUtil;
-
-    public MediaMetadataRetrieverUtil getMediaMetadataRetrieverUtil() {
-        return mediaMetadataRetrieverUtil;
-    }
-
-    private Video video;
-    /**
-     * 显示视频帧图片列表
-     *
-     * @param data 视频数据,包括地址与时长,宽高等
-     * @return
-     */
-    public VideoFramesView initVideo(Video data) {
-        if (data == null || data.getFilePath() == null) {
-            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoPath is null");
-            return this;
-        }
-        File videoFile = new File(data.getFilePath());
-        if (!videoFile.exists()) {
-            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile not exists");
-            return this;
-        }
-        if (!videoFile.canRead()) {
-            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile cant read");
-            return this;
-        }
-        if (data.getDuration() < 1) {
-            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "duration < 1");
-            return this;
-        }
-        if (mediaMetadataRetrieverUtil == null) {
-            mediaMetadataRetrieverUtil = new MediaMetadataRetrieverUtil(data.getFilePath(), data.getDuration());
-        }
-        this.video = data;
-        return this;
-    }
-
-    /**
-     * 显示视频帧图片列表
-     */
-    public VideoFramesView showVideoList() {
-        if (mediaMetadataRetrieverUtil != null)
-            mediaMetadataRetrieverUtil.initRv(recyclerView);
-        return this;
-    }
-
-    private Action1<Float> onTimeChangeListener;
-
-    public void setOnTimeChangeListener(Action1<Float> action1) {
-        onTimeChangeListener = action1;
-        postDelayed(new Runnable() {
-            @Override
-            public void run() {
-                firstStartX = line_start.getX();
-                firstEndX = line_end.getX();
-                lineW = line_start.getWidth();
-                rvW = recyclerView.getWidth();
-                long duration = mediaMetadataRetrieverUtil.getDuration();
-                if(maxVideoDuration > 0) {
-                    if(duration > maxVideoDuration) {
-                        firstEndX = firstStartX + ((maxVideoDuration * 1.0f / duration) * (rvW - lineW));
-                        line_end.setX(firstEndX);
-                    }
-                }
-                onTimeChangeListener.call((float) duration);
-            }
-        }, 100);
-    }
-
-    //开始的时间,单位秒
-    public long getStartPoint() {
-        return (long) (getStartPercent() * mediaMetadataRetrieverUtil.getDuration());
-    }
-
-    //总共的时长,单位秒
-    public long getLineDuration() {
-        return (long) (getPercent() * mediaMetadataRetrieverUtil.getDuration());
-    }
-    //结束的时间,单位秒
-    public long getEndPoint() {
-        return (long) (getEndPercent() * mediaMetadataRetrieverUtil.getDuration());
-    }
-
-    //最大剪切视频时长
-    private long maxVideoDuration;
-    public VideoFramesView setMaxDuration(long maxVideoDuration) {
-        this.maxVideoDuration = maxVideoDuration;
-        return this;
-    }
-    public void onDestroy(){
-        if(recyclerView != null && recyclerView.getAdapter() instanceof BaseQuickAdapter){
-            for (int i = 0; i < recyclerView.getAdapter().getItemCount(); i++) {
-                Object object = ((BaseQuickAdapter) recyclerView.getAdapter()).getItem(i);
-                if(object instanceof Bitmap){
-                    try {
-                        ((Bitmap) object).recycle();
-                    } catch (Exception e){
-                        e.printStackTrace();
-                    }
-                }
-            }
-        }
-    }
-}
+//package com.sheep.gamegroup.view.customview;
+//
+//import android.annotation.SuppressLint;
+//import android.content.Context;
+//import android.graphics.Bitmap;
+//import android.support.v7.widget.RecyclerView;
+//import android.util.AttributeSet;
+//import android.view.LayoutInflater;
+//import android.view.MotionEvent;
+//import android.view.View;
+//import android.widget.RelativeLayout;
+//
+//import com.chad.library.adapter.base.BaseQuickAdapter;
+//import com.chad.library.adapter.base.BaseViewHolder;
+//import com.sheep.gamegroup.model.entity.Video;
+//import com.sheep.gamegroup.util.LogUtil;
+//import com.sheep.gamegroup.util.MediaMetadataRetrieverUtil;
+//import com.sheep.jiuyan.samllsheep.R;
+//
+//import java.io.File;
+//import java.util.ArrayList;
+//import java.util.Locale;
+//
+//import rx.functions.Action1;
+//
+//
+///**
+// * Created by realicing on 2018/11/29.
+// * realicing@sina.com
+// * 显示本地视频文件对应的视频帧
+// */
+//public class VideoFramesView extends RelativeLayout {
+//    public VideoFramesView(Context context) {
+//        super(context);
+//        initView();
+//    }
+//
+//    public VideoFramesView(Context context, AttributeSet attrs) {
+//        super(context, attrs);
+//        initView();
+//    }
+//
+//    public VideoFramesView(Context context, AttributeSet attrs, int defStyleAttr) {
+//        super(context, attrs, defStyleAttr);
+//        initView();
+//    }
+//
+//    private RecyclerView recyclerView;
+//    private View line_start;
+//    private View line_end;
+//
+//    private void initView() {
+//        LayoutInflater.from(getContext()).inflate(R.layout.custom_video_frames_view, this, true);
+//        recyclerView = findViewById(R.id.recyclerView);
+//        line_start = findViewById(R.id.line_start);
+//        line_end = findViewById(R.id.line_end);
+//        line_start.setOnTouchListener(new OnTouchListener() {
+//            private float lastEventX;
+//
+//            @SuppressLint("ClickableViewAccessibility")
+//            @Override
+//            public boolean onTouch(View view, MotionEvent event) {
+//                float maxX = line_end.getX();
+//                float minX = maxX - (firstEndX - firstStartX);//结束位置 - 可以设置的长度
+//                switch (event.getAction()) {
+//                    case MotionEvent.ACTION_DOWN:
+//                        lastEventX = event.getX();
+//                        break;
+//                    case MotionEvent.ACTION_MOVE:
+//                        float mx = Math.max(firstStartX, view.getX() + event.getX() - lastEventX);
+//                        if (mx > maxX)
+//                            mx = maxX;
+//                        if (mx < minX) {
+//                            maxX += mx - minX;
+//                            line_end.setX(maxX);
+//                            view.setX(mx);
+//                        } else {
+//                            view.setX(mx);
+//                        }
+//                        if (onTimeChangeListener != null) {
+//                            onTimeChangeListener.call((maxX - mx) * video.getDuration() / (rvW - lineW));
+//                        }
+//                        break;
+//                    case MotionEvent.ACTION_UP:
+//                        break;
+//                    case MotionEvent.ACTION_CANCEL:
+//                        break;
+//                }
+//                view.invalidate();
+//                return true;
+//            }
+//        });
+//        line_end.setOnTouchListener(new OnTouchListener() {
+//            private float lastEventX;
+//
+//            @SuppressLint("ClickableViewAccessibility")
+//            @Override
+//            public boolean onTouch(View view, MotionEvent event) {
+//                float minX = line_start.getX();
+//                float maxX = firstEndX - firstStartX + minX;
+//                float endX = firstStartX + rvW - lineW;
+//                switch (event.getAction()) {
+//                    case MotionEvent.ACTION_DOWN:
+//                        lastEventX = event.getX();
+//                        break;
+//                    case MotionEvent.ACTION_MOVE:
+//                        float mx = Math.min(view.getX() + event.getX() - lastEventX, endX);
+//                        if (mx < minX)
+//                            mx = minX;
+//                        if (mx > maxX) {
+//                            minX += mx - maxX;
+//                            line_start.setX(minX);
+//                            view.setX(mx);
+//                        } else {
+//                            view.setX(mx);
+//                        }
+//                        if (onTimeChangeListener != null) {
+//                            onTimeChangeListener.call((mx - minX) * video.getDuration() / (rvW - lineW));
+//                        }
+//                        break;
+//                    case MotionEvent.ACTION_UP:
+//                        break;
+//                    case MotionEvent.ACTION_CANCEL:
+//                        break;
+//                }
+//                view.invalidate();
+//                return true;
+//            }
+//        });
+//    }
+//
+//    //开头线的进度
+//    public float getStartPercent() {
+//        if (line_start != null && recyclerView != null) {
+//            return (line_start.getX() - firstStartX) / (rvW - lineW);
+//        }
+//        return 0;
+//    }
+//
+//    private float firstStartX;//初始时开头的x位置
+//    private float firstEndX;//初始时结尾的x位置
+//    private int lineW;//开头与结尾线的宽度
+//    private int rvW;//图片列表的长度,减去lineW后==总进度的长度
+//
+//    //结尾线的进度
+//    public float getEndPercent() {
+//        if (line_end != null && recyclerView != null) {
+//            return 1.0f - ((firstStartX + rvW - lineW - line_end.getX()) / (rvW - lineW));
+//        }
+//        return 0;
+//    }
+//
+//    //总的进度
+//    public float getPercent() {
+//        if (line_end != null && recyclerView != null) {
+//            return (line_end.getX() - line_start.getX()) / (rvW - lineW);
+//        }
+//        return 0;
+//    }
+//
+//    public String getLineInfo() {
+//        return String.format(Locale.CHINA, "firstStartX = %f, firstEndX = %f, startX = %f, endX = %f, lineW = %d, rvW = %d, startPercent = %f, endPercent = %f, percent = %f", firstStartX, firstEndX, line_start.getX(), line_end.getX(), line_end.getWidth(), recyclerView.getWidth(), getStartPercent(), getEndPercent(), getPercent());
+//    }
+//
+//    private MediaMetadataRetrieverUtil mediaMetadataRetrieverUtil;
+//
+//    public MediaMetadataRetrieverUtil getMediaMetadataRetrieverUtil() {
+//        return mediaMetadataRetrieverUtil;
+//    }
+//
+//    private Video video;
+//    /**
+//     * 显示视频帧图片列表
+//     *
+//     * @param data 视频数据,包括地址与时长,宽高等
+//     * @return
+//     */
+//    public VideoFramesView initVideo(Video data) {
+//        if (data == null || data.getFilePath() == null) {
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoPath is null");
+//            return this;
+//        }
+//        File videoFile = new File(data.getFilePath());
+//        if (!videoFile.exists()) {
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile not exists");
+//            return this;
+//        }
+//        if (!videoFile.canRead()) {
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile cant read");
+//            return this;
+//        }
+//        if (data.getDuration() < 1) {
+//            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "duration < 1");
+//            return this;
+//        }
+//        if (mediaMetadataRetrieverUtil == null) {
+//            mediaMetadataRetrieverUtil = new MediaMetadataRetrieverUtil(data.getFilePath(), data.getDuration());
+//        }
+//        this.video = data;
+//        return this;
+//    }
+//
+//    /**
+//     * 显示视频帧图片列表
+//     */
+//    public VideoFramesView showVideoList() {
+//        if (mediaMetadataRetrieverUtil != null) {
+//            if(videoPathList != null)
+//                mediaMetadataRetrieverUtil.initRv(recyclerView, videoPathList);
+//            else
+//                mediaMetadataRetrieverUtil.initRv2(recyclerView);
+//        }
+//        return this;
+//    }
+//
+//    private Action1<Float> onTimeChangeListener;
+//
+//    public void setOnTimeChangeListener(Action1<Float> action1) {
+//        onTimeChangeListener = action1;
+//        postDelayed(new Runnable() {
+//            @Override
+//            public void run() {
+//                firstStartX = line_start.getX();
+//                firstEndX = line_end.getX();
+//                lineW = line_start.getWidth();
+//                rvW = recyclerView.getWidth();
+//                long duration = mediaMetadataRetrieverUtil.getDuration();
+//                if(maxVideoDuration > 0) {
+//                    if(duration > maxVideoDuration) {
+//                        firstEndX = firstStartX + ((maxVideoDuration * 1.0f / duration) * (rvW - lineW));
+//                        line_end.setX(firstEndX);
+//                    }
+//                }
+//                onTimeChangeListener.call((float) duration);
+//            }
+//        }, 100);
+//    }
+//
+//    //开始的时间,单位秒
+//    public long getStartPoint() {
+//        return (long) (getStartPercent() * mediaMetadataRetrieverUtil.getDuration());
+//    }
+//
+//    //总共的时长,单位秒
+//    public long getLineDuration() {
+//        return (long) (getPercent() * mediaMetadataRetrieverUtil.getDuration());
+//    }
+//    //结束的时间,单位秒
+//    public long getEndPoint() {
+//        return (long) (getEndPercent() * mediaMetadataRetrieverUtil.getDuration());
+//    }
+//
+//    //最大剪切视频时长
+//    private long maxVideoDuration;
+//    public VideoFramesView setMaxDuration(long maxVideoDuration) {
+//        this.maxVideoDuration = maxVideoDuration;
+//        return this;
+//    }
+//    public void onDestroy(){
+//        if(recyclerView != null && recyclerView.getAdapter() instanceof BaseQuickAdapter){
+//            for (int i = 0; i < recyclerView.getAdapter().getItemCount(); i++) {
+//                Object object = ((BaseQuickAdapter) recyclerView.getAdapter()).getItem(i);
+//                if(object instanceof Bitmap){
+//                    try {
+//                        ((Bitmap) object).recycle();
+//                    } catch (Exception e){
+//                        e.printStackTrace();
+//                    }
+//                }
+//            }
+//        }
+//    }
+//
+//    private ArrayList<String> videoPathList;
+//    public VideoFramesView setVideoPathList(ArrayList<String> videoPathList) {
+//        this.videoPathList = videoPathList;
+//        return this;
+//    }
+//}

+ 4 - 50
app/src/main/java/com/sheep/jiuyan/samllsheep/SheepApp.java

@@ -3,9 +3,6 @@ package com.sheep.jiuyan.samllsheep;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.AssetManager;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.StrictMode;
@@ -13,7 +10,6 @@ import android.support.multidex.MultiDex;
 import android.support.multidex.MultiDexApplication;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
-import android.util.Log;
 
 import com.baidu.location.BDAbstractLocationListener;
 import com.baidu.location.BDLocation;
@@ -21,13 +17,14 @@ import com.baidu.location.LocationClient;
 import com.baidu.location.LocationClientOption;
 import com.bumptech.glide.Glide;
 import com.danikula.videocache.HttpProxyCacheServer;
+import com.didi.virtualapk.PluginManager;
 import com.liulishuo.okdownload.OkDownload;
 import com.liulishuo.okdownload.core.dispatcher.DownloadDispatcher;
-import com.qiniu.android.storage.UploadManager;
 import com.sheep.gamegroup.di.components.DaggerNetComponent;
 import com.sheep.gamegroup.di.components.NetComponent;
 import com.sheep.gamegroup.di.modules.NetModule;
 import com.sheep.gamegroup.module.login.LoginAct;
+import com.sheep.gamegroup.module.plugin.util.PluginUtil;
 import com.sheep.gamegroup.usage.AppUsageManager;
 import com.sheep.gamegroup.util.ActivityManager;
 import com.sheep.gamegroup.util.AppUtil;
@@ -42,10 +39,7 @@ import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.gamegroup.util.MyFileNameGenerator;
 import com.sheep.gamegroup.util.RefreshUtil;
 import com.sheep.gamegroup.util.SysAppUtil;
-import com.sheep.gamegroup.util.TestUtil;
 import com.sheep.gamegroup.util.UMConfigUtils;
-import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.util.viewHelper.CacheImageUtil;
 import com.sheep.gamegroup.view.activity.GameCertificationActivity;
 import com.sheep.jiuyan.samllsheep.service.AutoCheckService;
 import com.sheep.jiuyan.samllsheep.service.DownloadService;
@@ -62,13 +56,8 @@ import com.umeng.socialize.PlatformConfig;
 import com.umeng.socialize.UMShareAPI;
 import com.youmi.android.offer.YmConfig;
 
-import org.wysaid.common.Common;
-import org.wysaid.nativePort.CGENativeLibrary;
 import org.xutils.x;
 
-import java.io.IOException;
-import java.io.InputStream;
-
 import cn.jpush.android.api.JPushInterface;
 
 /**
@@ -178,7 +167,6 @@ public class SheepApp extends MultiDexApplication {
             initUtils();
             detectFileUriExposure();
             ChannelContent.getInstance().initChannelContent(this);
-
         }
         refWatcher = LeakCanary.install(this);
     }
@@ -271,44 +259,8 @@ public class SheepApp extends MultiDexApplication {
         DownloadDispatcher.setMaxParallelRunningCount(1000);//在这里,下载框架好像有个bug,如果设置为5,第一个下载会占4个,第二个下载就只有一个在下载,就会失败
 
 //        RemitStoreOnSQLite.setRemitToDBDelayMillis(3000);
-        if(TestUtil.isDev())
-            initCgeLibrary();
     }
 
-    private void initCgeLibrary() {
-        //The second param will be passed as the second arg of the callback function.
-        //第二个参数根据自身需要设置, 将作为 loadImage 第二个参数回传
-        CGENativeLibrary.setLoadImageCallback(mLoadImageCallback, null);
-        for (String name : CGE_FILTER_IMGS) {
-            CacheImageUtil.cacheImg(ViewUtil.getNetImgByNameAndSuffix(name), null);
-        }
-    }
-    public static final String[] CGE_FILTER_IMGS = {"edgy_amber.png", "filmstock.png", "foggy_night.png", "late_sunset.png", "soft_warming.png", "wildbird.png", "hehe.jpg", "mapping0.jpg"};
-    public CGENativeLibrary.LoadImageCallback mLoadImageCallback = new CGENativeLibrary.LoadImageCallback() {
-
-        //Notice: the 'name' passed in is just what you write in the rule, e.g: 1.jpg
-        //注意, 这里回传的name不包含任何路径名, 仅为具体的图片文件名如 1.jpg
-        @Override
-        public Bitmap loadImage(String name, Object arg) {
-            String path = CacheImageUtil.getCacheImg(ViewUtil.getNetImgByNameAndSuffix(name));
-            if (path != null) {
-                return BitmapFactory.decodeFile(path);
-            }
-            return null;
-        }
-
-        @Override
-        public void loadImageOK(Bitmap bmp, Object arg) {
-            Log.i(Common.LOG_TAG, "Loading bitmap over, you can choose to recycle or cache");
-
-            //The bitmap is which you returned at 'loadImage'.
-            //You can call recycle when this function is called, or just keep it for further usage.
-            //唯一不需要马上recycle的应用场景为 多个不同的滤镜都使用到相同的bitmap
-            //那么可以选择缓存起来。
-            bmp.recycle();
-        }
-    };
-
     private void initBdLocationOption() {
         mLocationClient = new LocationClient(getApplicationContext());
         //声明LocationClient类
@@ -448,6 +400,7 @@ public class SheepApp extends MultiDexApplication {
             }
 
             if (mActivityCount == 0) {
+                PluginUtil.initPlugin();
                 if (ConfigUtil.getInstance().isUpgrade()) {
                     Beta.autoDownloadOnWifi = !BuildConfig.DEBUG;
                     Bugly.init(getApplicationContext(), Config.BUGLY_APPID, BuildConfig.DEBUG);
@@ -572,6 +525,7 @@ public class SheepApp extends MultiDexApplication {
     protected void attachBaseContext(Context base) {
         super.attachBaseContext(base);
         MultiDex.install(this);
+        PluginManager.getInstance(base).init();//插件化框架
     }
 
     @Override

+ 6 - 0
app/src/main/java/org/afinal/simplecache/ApiKey.java

@@ -70,6 +70,12 @@ public class ApiKey {
     public static final String getVideoSticker = "app/video/sticker";
     //查询话题列表
     public static final String getVideoTopic = "app/video/topic";
+    //客户端插件更新/插件获取
+    public static final String getPackageVersion = "app/version/package_version";
+
+    public static final String getPackageVersion(String package_name, String type, int version){
+        return String.format(Locale.CHINA, "%s?package_name=%s&type=%s&version=%d", getPackageVersion, package_name, type, version);
+    }
     public static final String pageKeyUrl(String baseUrl, int page, int per_page){
         return String.format(Locale.CHINA, "%s?page=%d&per_page=%d", baseUrl, page, per_page);
     }

+ 0 - 1
app/src/main/res/layout/act_video_detail.xml

@@ -11,7 +11,6 @@
         android:layout_height="wrap_content"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
-
     <com.github.ybq.android.spinkit.SpinKitView
         android:id="@+id/video_loading"
         style="@style/SpinKitView.Large.ThreeBounce"

+ 0 - 3
app/src/sheeptestjiguang/res/values/strings.xml

@@ -1,3 +0,0 @@
-<resources>
-    <string name="app_name">小绵羊极光</string>
-</resources>

+ 2 - 1
build.gradle

@@ -17,7 +17,8 @@ buildscript {
         classpath 'com.novoda:bintray-release:0.5.0'
         //Realm数据库
        // classpath "io.realm:realm-gradle-plugin:3.7.0"
-//        classpath 'com.didi.virtualapk:gradle:0.9.1'
+        //插件化
+        classpath 'com.didi.virtualapk:gradle:0.9.8.6'
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
 

+ 14 - 0
media/.gitignore

@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+/.idea
+/kfzslibrary
+/banner
+/app/src/main/obj
+*.txt

+ 1 - 0
media/app/.gitignore

@@ -0,0 +1 @@
+/build

+ 101 - 0
media/app/build.gradle

@@ -0,0 +1,101 @@
+apply plugin: 'com.android.application'
+apply plugin: 'com.didi.virtualapk.plugin'
+
+android {
+    compileSdkVersion ANDROID_COMPILE_SDK_VERSION as int
+
+    defaultConfig {
+        applicationId "com.kfzs.cfyl.media"
+        minSdkVersion ANDROID_MIN_SDK_VERSION as int
+        targetSdkVersion ANDORID_TARGET_SDK_VERSION as int
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+        ndk {
+            abiFilters "armeabi-v7a"//, 'x86'//, 'armeabi-v7a', 'x86_64', 'arm64-v8a'
+        }
+    }
+
+    signingConfigs {
+        config {
+            keyAlias 'sheep'
+            keyPassword 'zhaoyi2004'
+            storeFile file('.././../sign.jks')
+            storePassword 'zhaoyi2004'
+            v1SigningEnabled true
+            v2SigningEnabled false
+        }
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            signingConfig signingConfigs.config
+        }
+        debug {
+            signingConfig signingConfigs.config
+        }
+    }
+//    splits {
+//        abi {
+//            enable true
+//            reset()
+//            include 'x86', 'armeabi-v7a', 'arm64-v8a'
+////            include 'mips', 'arm64-v8a', 'x86', 'x86_64', 'armeabi', 'armeabi-v7a'
+//            universalApk false
+//        }
+//    }
+
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+    implementation "com.android.support:appcompat-v7:$supportLibVersion"
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.2'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+    implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
+    implementation project(':share_library')
+    implementation("com.android.support:recyclerview-v7:$supportLibVersion")
+    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
+    implementation 'com.github.ybq:Android-SpinKit:1.1.0'
+    //All arch: armeabi, armeabi-v7a, arm64-v8a, mips, x86
+    implementation 'org.wysaid:gpuimage-plus:2.5.1'
+    //Pure graphics lib without ffmpeg. (all arch for branch 'min')
+//    implementation 'org.wysaid:gpuimage-plus:2.5.1-min'
+    implementation('com.github.bumptech.glide:glide:4.1.1') {
+        exclude group: 'com.android.support', module: 'support-fragment'
+//        exclude group: 'com.github.bumptech.glide', module: 'gifdecoder'
+//        exclude group: 'com.github.bumptech.glide', module: 'disklrucache'
+//        exclude group: 'com.github.bumptech.glide', module: 'annotations'
+    }
+    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
+}
+
+
+virtualApk {
+    packageId = 0x6f             // The package id of Resources.
+    targetHost='../app' // The path of application module in host project.
+    applyHostMapping = true      // [Optional] Default value is true.
+    forceUseHostDependences = true
+}
+//static def releaseTime() {
+//    return new Date().format("MMddHHmm", TimeZone.getDefault())
+//}
+//在apk文件后边生成版本号信息
+android.applicationVariants.all {
+    variant ->
+        variant.outputs.all {
+            output ->
+//                if (buildType.name == "release") {
+                outputFileName = "media_release.apk"
+//                outputFileName = "media_${output.getFilter(com.android.build.OutputFile.ABI)}.apk"
+//                outputFileName = "media_v${versionCode}-${releaseTime()}_${output.getFilter(com.android.build.OutputFile.ABI)}.apk"
+//                }
+
+        }
+}

+ 23 - 0
media/app/proguard-rules.pro

@@ -0,0 +1,23 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+
+-keep class wseemann.media.FFmpegMediaMetadataRetriever.** { *; }

+ 26 - 0
media/app/src/androidTest/java/com/kfzs/cfyl/media/ExampleInstrumentedTest.java

@@ -0,0 +1,26 @@
+package com.kfzs.cfyl.media;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.kfzs.cfyl.media", appContext.getPackageName());
+    }
+}

+ 29 - 0
media/app/src/main/AndroidManifest.xml

@@ -0,0 +1,29 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.kfzs.cfyl.media">
+
+    <application
+        android:allowBackup="true"
+        android:name=".MediaApp"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+
+        <activity android:name=".activity.MainActivity">
+
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.VIEW" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".activity.ActCutVideo"
+            android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+            android:screenOrientation="portrait"/>
+        <activity android:name=".activity.ActEditVideo"
+            android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+            android:screenOrientation="portrait"/>
+    </application>
+</manifest>

BIN
media/app/src/main/assets/edgy_amber.png


BIN
media/app/src/main/assets/filmstock.png


BIN
media/app/src/main/assets/foggy_night.png


BIN
media/app/src/main/assets/hehe.jpg


BIN
media/app/src/main/assets/late_sunset.png


BIN
media/app/src/main/assets/mapping0.jpg


BIN
media/app/src/main/assets/soft_warming.png


BIN
media/app/src/main/assets/wildbird.png


+ 146 - 0
media/app/src/main/java/com/kfzs/cfyl/media/BaseActivity.java

@@ -0,0 +1,146 @@
+package com.kfzs.cfyl.media;
+
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+
+import com.kfzs.cfyl.media.dialog.DialogProgress;
+import com.kfzs.cfyl.media.util.G;
+
+import java.lang.reflect.Field;
+
+/**
+ * Created by kemllor on 2017/12/15.
+ */
+
+public abstract class BaseActivity extends AppCompatActivity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        G.init(getResources());
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            Window win = getWindow();
+            WindowManager.LayoutParams winParams = win.getAttributes();
+            final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+            winParams.flags |= bits;
+            win.setAttributes(winParams);
+        }
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+            Window window = getWindow();
+            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
+                    | View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
+            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+            window.setStatusBarColor(Color.TRANSPARENT);
+        }
+
+        ActionBar actionBar = getSupportActionBar();
+        if (actionBar != null) {
+            actionBar.setCustomView(R.layout.title);
+            actionBar.hide();
+            actionBar.setDisplayShowCustomEnabled(true);
+            actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
+            actionBar.setElevation(0);
+            Toolbar toolbar = (Toolbar) actionBar.getCustomView().getParent();
+            toolbar.setContentInsetsRelative(0, 0);
+        }
+        setContentView(getLayoutId());
+        initView();
+        initListener();
+        initData();
+    }
+
+    protected abstract int getLayoutId();
+
+    public abstract void initView();
+
+    public void initListener() {
+
+    }
+
+    public void initData() {
+
+    }
+
+    @Override
+    protected void onDestroy() {
+        fixHuaweiLeak();
+        super.onDestroy();
+    }
+
+
+
+    protected DialogProgress dialog;
+    public boolean isShowing() {
+        return dialog != null && dialog.getAlertDialog() != null && dialog.getAlertDialog().isShowing();
+    }
+
+    public DialogProgress showProgress() {
+        hideProgress();
+        dialog = DialogProgress.showDialog(this);
+        return dialog;
+    }
+
+    protected DialogProgress showProgress(boolean cancel) {
+        hideProgress();
+        dialog = DialogProgress.showDialog(this, cancel);
+        return dialog;
+    }
+
+
+    public void hideProgress() {
+        if (isShowing()) {
+            try {
+                dialog.getAlertDialog().dismiss();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+    //解决华为手机内存泄漏问题
+    private static Field[] leakFields = new Field[2];
+    private static boolean[] hasLeakFields = {true, true};
+    private static String[] leakFieldNames = {"mLastSrvView", "mNextServedView"};
+
+    private void fixHuaweiLeak() {
+        boolean goon = false;
+        for (boolean has : hasLeakFields) {
+            goon = goon || has;
+            if (goon) break;
+        }
+        if (!goon) return;
+
+        InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+        if (imm == null) {
+            return;
+        }
+
+        for (int i = 0; i < leakFieldNames.length; i++) {
+            try {
+                if (leakFields[i] == null) {
+                    leakFields[i] = imm.getClass().getDeclaredField(leakFieldNames[i]);
+                }
+                if (leakFields[i] == null) {
+                    hasLeakFields[i] = false;
+                }
+                if (leakFields[i] != null) {
+                    leakFields[i].setAccessible(true);
+                    leakFields[i].set(imm, null);
+                }
+            } catch (Throwable t) {
+                t.printStackTrace();
+            }
+        }
+    }
+}

+ 36 - 0
media/app/src/main/java/com/kfzs/cfyl/media/BaseContainerActivity.java

@@ -0,0 +1,36 @@
+package com.kfzs.cfyl.media;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+
+
+/**
+ * Created by realicing on 2018/11/2.
+ * realicing@sina.com
+ */
+public abstract class BaseContainerActivity extends BaseActivity {
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.common_container;
+    }
+
+    protected Fragment fragment;
+
+    @Override
+    public void initView() {
+
+        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+        fragment = getSupportFragmentManager().findFragmentByTag("tag");
+        if (fragment == null) {
+            fragment = initFragment();
+            transaction.add(R.id.frame_container, fragment, "tag");
+            transaction.commitAllowingStateLoss();
+        } else {
+            transaction.replace(R.id.frame_container, fragment);
+            transaction.commitAllowingStateLoss();
+        }
+
+    }
+
+    protected abstract Fragment initFragment();
+}

+ 103 - 0
media/app/src/main/java/com/kfzs/cfyl/media/BaseFragment.java

@@ -0,0 +1,103 @@
+package com.kfzs.cfyl.media;
+
+import android.os.Bundle;
+import android.support.annotation.IdRes;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public abstract class BaseFragment extends Fragment {
+
+    protected View mView;
+    /**
+     * 是否是第一次初始化,防止重复加载些东西用
+     */
+    protected boolean mIsFirstInit = true;
+
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setRetainInstance(true);
+    }
+
+
+    /**
+     * 注意用 mIsFirstInit 判断,防止重复加载
+     *
+     * @param inflater
+     * @param container
+     * @param savedInstanceState
+     * @return
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        if (mView == null) {
+            mIsFirstInit = true;
+            mView = inflater.inflate(getLayoutId(), null);
+        } else {
+            mIsFirstInit = false;
+        }
+        return mView;
+    }
+
+
+    public abstract int getLayoutId();
+
+    public abstract void onViewCreated();
+
+    /**
+     * 一般要继承这个方法
+     *
+     * @param view
+     * @param savedInstanceState
+     */
+    @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        onViewCreated();
+    }
+
+    protected boolean firstVisibleToUser = true;
+
+    @Override
+    public void setUserVisibleHint(boolean isVisibleToUser) {
+        super.setUserVisibleHint(isVisibleToUser);
+        if (isVisibleToUser && mView != null) {
+            if (firstVisibleToUser) {
+                initViewOnVisibleToUser();
+            }
+            initDataOnVisibleToUser();
+            firstVisibleToUser = false;
+        }
+    }
+
+    protected void initViewOnVisibleToUser() {
+
+    }
+
+    protected void initDataOnVisibleToUser() {
+
+    }
+
+    /**
+     * 万能的找View类
+     *
+     * @param id
+     * @param <T>
+     * @return
+     */
+    public <T extends View> T findViewById(@IdRes int id) {
+        if(mView != null)
+            return mView.findViewById(id);
+        return null;
+    }
+
+}

+ 143 - 0
media/app/src/main/java/com/kfzs/cfyl/media/MediaApp.java

@@ -0,0 +1,143 @@
+package com.kfzs.cfyl.media;
+
+import android.app.Application;
+import android.content.res.AssetManager;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Log;
+
+import org.wysaid.common.Common;
+import org.wysaid.nativePort.CGENativeLibrary;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Created by realicing on 2018/12/10.
+ * realicing@sina.com
+ */
+public class MediaApp extends Application {
+    @Override
+    public void onCreate() {
+        super.onCreate();
+//        initGlide(getApplicationContext());
+        initCgeLibrary();
+    }
+
+    private void initCgeLibrary() {
+        //The second param will be passed as the second arg of the callback function.
+        //第二个参数根据自身需要设置, 将作为 loadImage 第二个参数回传
+        CGENativeLibrary.setLoadImageCallback(mLoadImageCallback, null);
+    }
+
+    public CGENativeLibrary.LoadImageCallback mLoadImageCallback = new CGENativeLibrary.LoadImageCallback() {
+
+        //Notice: the 'name' passed in is just what you write in the rule, e.g: 1.jpg
+        //注意, 这里回传的name不包含任何路径名, 仅为具体的图片文件名如 1.jpg
+        @Override
+        public Bitmap loadImage(String name, Object arg) {
+
+            Log.i(Common.LOG_TAG, "Loading file: " + name);
+            AssetManager am = getAssets();
+            InputStream is;
+            try {
+                is = am.open(name);
+            } catch (IOException e) {
+                Log.e(Common.LOG_TAG, "Can not open file " + name);
+                return null;
+            }
+
+            return BitmapFactory.decodeStream(is);
+        }
+
+        @Override
+        public void loadImageOK(Bitmap bmp, Object arg) {
+            Log.i(Common.LOG_TAG, "Loading bitmap over, you can choose to recycle or cache");
+
+            //The bitmap is which you returned at 'loadImage'.
+            //You can call recycle when this function is called, or just keep it for further usage.
+            //唯一不需要马上recycle的应用场景为 多个不同的滤镜都使用到相同的bitmap
+            //那么可以选择缓存起来。
+            bmp.recycle();
+        }
+    };
+}
+//    public static void initGlide(Registry registry){
+//        LogUtil.println("VideoUtil", "initGlide");
+//        registry.append(VideoFrame.class, Bitmap.class, new ResourceDecoder<VideoFrame, Bitmap>() {
+//            @Override
+//            public boolean handles(VideoFrame source, Options options) throws IOException {
+//                return true;
+//            }
+//
+//            @Nullable
+//            @Override
+//            public Resource<Bitmap> decode(VideoFrame source, int width, int height, Options options) throws IOException {
+//                final Bitmap bitmap = VideoUtil.getVideoFrameBitmap(source);
+//                return new Resource<Bitmap>() {
+//                    @Override
+//                    public Class<Bitmap> getResourceClass() {
+//                        return Bitmap.class;
+//                    }
+//
+//                    @Override
+//                    public Bitmap get() {
+//                        return bitmap;
+//                    }
+//
+//                    @Override
+//                    public int getSize() {
+//                        if (bitmap != null)
+//                            return bitmap.getRowBytes() * bitmap.getHeight();// 获取大小并返回;Bitmap所占用的内存空间数等于Bitmap的每一行所占用的空间数乘以Bitmap的行数
+//                        else return 0;
+//                    }
+//
+//                    @Override
+//                    public void recycle() {
+//                        if (bitmap != null) {
+//                            try {
+//                                bitmap.recycle();
+//                            } catch (Exception ignore) {
+//
+//                            }
+//                        }
+//                    }
+//                };
+//            }
+//        });
+//        Glide.get(getApplicationContext()).getRegistry().register(VideoFrame.class, Bitmap.class, new ResourceTranscoder<VideoFrame, Bitmap>() {
+//            @Override
+//            public Resource<Bitmap> transcode(Resource<VideoFrame> toTranscode) {
+//                final VideoFrame source = toTranscode.get();
+//                final Bitmap bitmap = VideoUtil.getVideoFrameBitmap(source);
+//                return new Resource<Bitmap>() {
+//                    @Override
+//                    public Class<Bitmap> getResourceClass() {
+//                        return Bitmap.class;
+//                    }
+//
+//                    @Override
+//                    public Bitmap get() {
+//                        return bitmap;
+//                    }
+//
+//                    @Override
+//                    public int getSize() {
+//                        if (bitmap != null)
+//                            return bitmap.getRowBytes() * bitmap.getHeight();// 获取大小并返回;Bitmap所占用的内存空间数等于Bitmap的每一行所占用的空间数乘以Bitmap的行数
+//                        else return 0;
+//                    }
+//
+//                    @Override
+//                    public void recycle() {
+//                        if (bitmap != null) {
+//                            try {
+//                                bitmap.recycle();
+//                            } catch (Exception ignore) {
+//
+//                            }
+//                        }
+//                    }
+//                };
+//            }
+//        });

+ 311 - 0
media/app/src/main/java/com/kfzs/cfyl/media/activity/ActCutVideo.java

@@ -0,0 +1,311 @@
+package com.kfzs.cfyl.media.activity;
+
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.support.v4.app.Fragment;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.VideoView;
+
+import com.alibaba.fastjson.JSONObject;
+import com.kfzs.cfyl.media.BaseContainerActivity;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.api.IdChooser;
+import com.kfzs.cfyl.media.customview.VideoFramesView;
+import com.kfzs.cfyl.media.fragment.FgtDiscoveryTopic;
+import com.kfzs.cfyl.media.util.G;
+import com.kfzs.cfyl.media.util.KeyEventUtil;
+import com.kfzs.cfyl.media.util.ListUtil;
+import com.kfzs.cfyl.media.util.VideoUtil;
+import com.kfzs.cfyl.media.util.ViewUtil;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import rx.functions.Action1;
+
+/**
+ * Created by realicing on 2018/11/9.
+ * realicing@sina.com
+ * 添加话题并剪切视频
+ */
+public class ActCutVideo extends BaseContainerActivity implements MediaPlayer.OnInfoListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, IdChooser {
+
+    VideoView videoView;
+    View video_loading;
+    VideoFramesView videoFramesView;
+    TextView edit_video_time_tv;
+
+    TextView edit_video_topic_tv;
+    TextView edit_video_sure_tv;
+    View frame_container;
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.act_cut_video;
+    }
+
+
+    public static final long MAX_VIDEO_DURATION = 15_000L;//视频最大时长,超过需要剪切
+    private Video data;
+
+    private ArrayList<String> arrayList;//主题列表
+
+
+    @Override
+    protected Fragment initFragment() {
+        return new FgtDiscoveryTopic();
+    }
+    @Override
+    public void initView() {
+        super.initView();
+
+        Intent intent = getIntent();
+        arrayList = intent.getStringArrayListExtra(ArrayList.class.getSimpleName());
+        if (arrayList != null && fragment instanceof FgtDiscoveryTopic)
+            ((FgtDiscoveryTopic) fragment).loadData(arrayList);
+        data = JSONObject.parseObject(intent.getStringExtra(String.class.getSimpleName()), Video.class);
+        Uri uri = Uri.parse(data.getFilePath());
+
+        videoView = findViewById(R.id.videoView);
+        video_loading = findViewById(R.id.video_loading);
+        videoFramesView = findViewById(R.id.videoFramesView);
+        edit_video_time_tv = findViewById(R.id.edit_video_time_tv);
+        edit_video_topic_tv = findViewById(R.id.edit_video_topic_tv);
+        edit_video_sure_tv = findViewById(R.id.edit_video_sure_tv);
+        frame_container = findViewById(R.id.frame_container);
+
+        videoView.setOnInfoListener(this);
+        videoView.setOnPreparedListener(this);
+        videoView.setOnErrorListener(this);
+        videoView.setOnCompletionListener(this);
+//        videoView.setMediaController(new MediaController(this));
+        videoView.setVideoURI(uri);
+        videoFramesView.initVideo(data).setMaxDuration(MAX_VIDEO_DURATION).showVideoList(this).setOnTimeChangeListener(new Action1<Float>() {
+            @Override
+            public void call(Float duration) {
+                if (duration == null)
+                    return;
+                if (videoFramesView.getVisibility() == View.VISIBLE)
+                    checkDuration(duration.longValue());
+                edit_video_time_tv.setText(getString(R.string.has_choose_x_second, new DecimalFormat("#.#").format(duration / 1000.0f)));
+                edit_video_time_tv.append("\t");
+                edit_video_time_tv.append(String.valueOf(duration));
+                edit_video_time_tv.append("\t");
+                edit_video_time_tv.append(String.valueOf(data.getDuration()));
+                edit_video_time_tv.append("\t");
+                edit_video_time_tv.append(String.format(Locale.CHINA, "%.1f秒-%.1f秒", videoFramesView.getStartPoint() / 1000.0f, videoFramesView.getEndPoint() / 1000.0f));
+                edit_video_time_tv.append("\t");
+                edit_video_time_tv.append(videoFramesView.getLineInfo());
+            }
+        });
+        //隐藏视频剪切相关view
+        edit_video_time_tv.setVisibility(View.INVISIBLE);
+        videoFramesView.setVisibility(View.INVISIBLE);
+    }
+
+    private static final String TAG = ActCutVideo.class.getSimpleName();
+
+    //检查有没有设置剪切视频的时长
+    private void checkDuration(long duration) {
+        LogUtil.println(TAG, data.getDuration(), duration);
+        if ((data.getDuration() - duration) >= 500) {
+            edit_video_sure_tv.setText(BTN_TEXT_CUT);
+        } else {
+            edit_video_sure_tv.setText(BTN_TEXT_FINISH);
+        }
+    }
+
+
+    //播放或者暂停
+    private void playOrPause() {
+        if (videoView.isPlaying()) {
+            pause();
+        } else {
+            play();
+        }
+    }
+
+    //播放
+    private void play() {
+        if (videoView == null) {
+            return;
+        }
+        videoView.start();
+    }
+
+    //暂停
+    private void pause() {
+        if (videoView == null) {
+            return;
+        }
+        videoView.pause();
+    }
+
+    //销毁
+    private void destroy() {
+        if (videoView == null) {
+            return;
+        }
+        videoView.stopPlayback();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (!isPauseByUser)
+            play();
+    }
+
+    //是否是用户手机暂停
+    private boolean isPauseByUser;
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if (videoView != null && videoView.isPlaying())
+            isPauseByUser = false;
+        if (video_loading != null)
+            video_loading.setVisibility(View.VISIBLE);
+        pause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        destroy();
+        if (videoFramesView != null)
+            videoFramesView.onDestroy();
+        super.onDestroy();
+    }
+
+    @Override
+    public boolean onInfo(MediaPlayer mediaPlayer, int what, int extra) {
+        LogUtil.println("ActPlayVideo", "onInfo what = " + what + " extra = " + extra);
+        if (!mediaPlayer.isLooping())
+            mediaPlayer.setLooping(true);
+        switch (what) {
+            case MediaPlayer.MEDIA_INFO_BUFFERING_START:
+                LogUtil.println("ActPlayVideo", "onInfo", "正在缓冲");
+                if (video_loading != null)
+                    video_loading.setVisibility(View.VISIBLE);
+                break;
+            case MediaPlayer.MEDIA_INFO_BUFFERING_END:
+            case MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:
+                LogUtil.println("ActPlayVideo", "onInfo", "缓冲完成");
+                //缓存完成,继续播放
+                if (video_loading != null)
+                    video_loading.setVisibility(View.GONE);
+                break;
+        }
+        return false;
+    }
+
+    @Override
+    public void onPrepared(MediaPlayer mediaPlayer) {
+        LogUtil.println("ActPlayVideo", "onPrepared");
+        if (video_loading != null)
+            video_loading.setVisibility(View.GONE);
+    }
+
+    @Override
+    public boolean onError(MediaPlayer mediaPlayer, int what, int extra) {
+        LogUtil.println("ActPlayVideo", "onInfo what = " + what + " extra = " + extra);
+        return false;
+    }
+
+    @Override
+    public void onCompletion(MediaPlayer mediaPlayer) {
+        LogUtil.println("ActPlayVideo", "onCompletion");
+    }
+
+    //点击话题进行切换
+    public void onClickTopic(View view) {
+        ViewUtil.toggleVisibility(frame_container);
+        ViewUtil.setText(edit_video_sure_tv, BTN_TEXT_NEXT);
+        if (ViewUtil.isVisible(frame_container)) {
+            ViewUtil.setVisibility2(edit_video_time_tv, false);
+            ViewUtil.setVisibility2(videoFramesView, false);
+        }
+    }
+
+    //点击返回
+    public void onClickBackImg(View view) {
+        KeyEventUtil.sendKeyDownUp(KeyEvent.KEYCODE_BACK);
+    }
+
+    private static final String BTN_TEXT_NEXT = "下一步";
+    private static final String BTN_TEXT_CUT = "剪切";
+    private static final String BTN_TEXT_FINISH = "完成";
+
+    //点击确定
+    public void onClickSure(View view) {
+        String btnText = ((TextView) view).getText().toString();
+        switch (btnText) {
+            case BTN_TEXT_NEXT:
+                showCut();
+                break;
+            case BTN_TEXT_CUT:
+                tryCut();
+                break;
+            case BTN_TEXT_FINISH:
+                finishCut();
+                break;
+        }
+    }
+
+    private void finishCut() {//完成剪切并返回数据
+        Intent intent = new Intent();
+        intent.putExtra(Video.class.getSimpleName(), data);
+        setResult(RESULT_OK, intent);
+        finish();
+    }
+
+    private void tryCut() {//其次完成编辑
+        showProgress().getTextView().setText("剪切视频中");
+        VideoUtil.tryCutVideo(data.getFilePath(), videoFramesView.getStartPoint() * 1000, videoFramesView.getLineDuration() * 1000, new Action1<Object>() {
+            @Override
+            public void call(final Object result) {
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (result instanceof Video) {
+                            Video video = (Video) result;
+                            data.setFilePath(video.getFilePath());
+                            data.setWidth(video.getWidth());
+                            data.setHeight(video.getHeight());
+                            data.setDuration(video.getDuration());
+                            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + video.getFilePath())));
+                            hideProgress();
+                            G.showToast(getApplicationContext(), "剪切完成");
+                            finishCut();
+                        } else if (result instanceof Throwable) {
+                            hideProgress();
+                            G.showToast(getApplicationContext(), ((Throwable) result).getMessage());
+                        }
+                    }
+                });
+            }
+        });
+    }
+
+    private void showCut() {//首先隐藏话题列表
+        ViewUtil.setVisibility(frame_container, false);
+        ViewUtil.setVisibility2(edit_video_time_tv, true);
+        ViewUtil.setVisibility2(videoFramesView, true);
+        checkDuration(videoFramesView.getLineDuration());
+    }
+
+    @Override
+    public void onSelectId(int id) {
+        String item = ListUtil.getItem(arrayList, id);
+        if (item != null) {
+            data.setTopicIndex(id);
+            ViewUtil.setText(edit_video_topic_tv, "#%s#", item);
+        }
+    }
+}

+ 322 - 0
media/app/src/main/java/com/kfzs/cfyl/media/activity/ActEditVideo.java

@@ -0,0 +1,322 @@
+package com.kfzs.cfyl.media.activity;
+
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.support.v4.app.Fragment;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+
+import com.kfzs.cfyl.media.BaseContainerActivity;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.api.Filterble;
+import com.kfzs.cfyl.media.api.IFilter;
+import com.kfzs.cfyl.media.bean.Size;
+import com.kfzs.cfyl.media.fragment.FgtChooseEditList;
+import com.kfzs.cfyl.media.util.BitmapUtil;
+import com.kfzs.cfyl.media.util.G;
+import com.kfzs.cfyl.media.util.ViewUtil;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
+
+import org.wysaid.common.Common;
+import org.wysaid.nativePort.CGEFFmpegNativeLibrary;
+import org.wysaid.nativePort.CGENativeLibrary;
+import org.wysaid.view.VideoPlayerGLSurfaceView;
+
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/11/9.
+ * realicing@sina.com
+ * 编辑视频
+ */
+public class ActEditVideo extends BaseContainerActivity implements Filterble {
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.act_edit_video;
+    }
+
+    VideoPlayerGLSurfaceView mPlayerView;
+
+    private Video data;
+
+    private String mCurrentConfig;
+    private float mIntensity = 1.0f;
+
+    public static final int REQUEST_CODE_PICK_VIDEO = 1;
+
+    private VideoPlayerGLSurfaceView.PlayCompletionCallback playCompletionCallback = new VideoPlayerGLSurfaceView.PlayCompletionCallback() {
+        @Override
+        public void playComplete(MediaPlayer player) {
+            Log.i(Common.LOG_TAG, "The video playing is over, restart...");
+            player.start();
+        }
+
+        @Override
+        public boolean playFailed(MediaPlayer player, final int what, final int extra) {
+            G.showToast(getApplicationContext(), "播放出错,请稍候重试");
+            return true;
+        }
+    };
+    @Override
+    public void initView() {
+        if (this instanceof BaseContainerActivity) {
+            super.initView();
+        }
+        mPlayerView = findViewById(R.id.videoGLSurfaceView);
+        data = (Video) getIntent().getSerializableExtra(Video.class.getSimpleName());
+        mPlayerView.setZOrderOnTop(false);
+        mPlayerView.setZOrderMediaOverlay(true);
+
+
+        mPlayerView.setPlayerInitializeCallback(new VideoPlayerGLSurfaceView.PlayerInitializeCallback() {
+            @Override
+            public void initPlayer(final MediaPlayer player) {
+                //针对网络视频进行进度检查
+                player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
+                    @Override
+                    public void onBufferingUpdate(MediaPlayer mp, int percent) {
+                        Log.i(Common.LOG_TAG, "Buffer update: " + percent);
+                        if (percent == 100) {
+                            Log.i(Common.LOG_TAG, "缓冲完毕!");
+                            player.setOnBufferingUpdateListener(null);
+                        }
+                    }
+                });
+            }
+        });
+
+        mPlayerView.setVideoUri(Uri.parse(data.getFilePath()), new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
+            @Override
+            public void playPrepared(MediaPlayer player) {
+                Log.i(Common.LOG_TAG, "The video is prepared to play");
+                player.start();
+            }
+        }, playCompletionCallback);
+
+        seekBarLl = findViewById(R.id.seekBarLl);
+        if (ViewUtil.isVisible(seekBarLl)) {
+            loadTest();
+        }
+    }
+
+    //点击完成
+    public void onClickCommit(View view) {
+        if(TextUtils.isEmpty(mCurrentConfig)){
+            setResultAndFinish();
+            return;
+        }
+        showProgress().getTextView().setText("编辑视频中");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                final String filePath = tryGenerateVideoWithFilter();
+                runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + filePath)));
+                        data.setFilePath(filePath);
+                        hideProgress();
+                        G.showToast(getApplicationContext(), "编辑完成");
+                        setResultAndFinish();
+                    }
+                });
+            }
+        }).start();
+    }
+
+    private void setResultAndFinish() {
+        Intent intent = new Intent();
+        intent.putExtra(Video.class.getSimpleName(), data);
+        setResult(RESULT_OK, intent);
+        ActEditVideo.this.finish();
+    }
+
+    private String tryGenerateVideoWithFilter() {
+        String srcFilPath = data.getFilePath();
+        String outputFilename = String.format(Locale.CHINA, "%s_%d_%f.mp4", srcFilPath.substring(0, srcFilPath.lastIndexOf(".")), mCurrentConfig.hashCode(), mIntensity);
+        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.sheep_logo_3);
+        //left 30px top 60px width 750
+        Bitmap logo = BitmapUtil.createBigLogo(bmp, new Size().setWidth(data.getWidth()).setHeight(data.getHeight()).setX(data.getWidth() * 30 / 750).setY(data.getWidth() * 60 / 750));
+        bmp.recycle();
+        CGEFFmpegNativeLibrary.generateVideoWithFilter(outputFilename, srcFilPath, mCurrentConfig, mIntensity, logo, CGENativeLibrary.TextureBlendMode.CGE_BLEND_ADDREV, 1.0f, false);
+
+        LogUtil.println(ActEditVideo.class.getSimpleName(), "Done! The file is generated at: " + outputFilename);
+        return outputFilename;
+    }
+
+    //设置滤镜
+    @Override
+    public void setFilter(IFilter filter) {
+        if (mPlayerView != null && filter != null && filter.getConfig() != null) {
+            mCurrentConfig = filter.getConfig();
+            mPlayerView.setFilterWithConfig(mCurrentConfig);
+        }
+    }
+
+    @Override
+    public void setFilterIntensity(float intensity) {
+        if (mPlayerView != null) {
+            mIntensity = intensity;
+            mPlayerView.setFilterIntensity(mIntensity);
+        }
+    }
+
+    //下面为测试代码
+
+    private void loadTest() {
+
+        for (int i = 0; i < 6; i++) {
+            SeekBar sb = new SeekBar(getApplicationContext());
+            sb.setMax(100);
+            sb.setProgress(50);
+            seekBarLl.addView(sb);
+            final int finalI = i;
+            sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
+                    onSeek(finalI, progress);
+                }
+
+                @Override
+                public void onStartTrackingTouch(SeekBar seekBar) {
+
+                }
+
+                @Override
+                public void onStopTrackingTouch(SeekBar seekBar) {
+
+                }
+            });
+        }
+    }
+
+    LinearLayout seekBarLl;
+
+    private int[] progresses = {50, 50, 50, 50, 50, 50};
+
+    private float getPercent(int index) {
+        return (progresses[index] - 50) / 50.0f;
+    }
+
+    private int getPercent(int index, int max) {
+        return progresses[index] * max / 100;
+    }
+
+    private void onSeekHsv(int index, int progress) {
+        progresses[index] = progress;//色调(H),饱和度(S),明度(V)
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust hsv %.2f %.2f %.2f %.2f %.2f %.2f", getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i)));
+    }
+
+    private void onSeekHsl(int index, int progress) {
+        progresses[index] = progress;//0,0,0 色相(H)、饱和度(S)、明度(L)
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust hsl %.2f %.2f %.2f", getPercent(i++), getPercent(i++), getPercent(i)));
+    }
+
+    private void onSeekRgb(int index, int progress) {
+        progresses[index] = progress;//0,0,255,255 黑<白、反光<亮度
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@curve RGB(%d, %d)(%d, %d)", getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i, 255)));
+    }
+
+    private void onSeekLevel(int index, int progress) {
+        progresses[index] = progress;//0,1,1
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust level %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i)));
+    }
+
+    private void onSeekSaturation(int index, int progress) {
+        progresses[index] = progress;//1 饱和度
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust saturation %.2f ", getPercent(0)));
+    }
+
+    private void onSeek/*ColorBalance*/(int index, int progress) {
+        progresses[index] = progress;//0,0,0 红绿蓝
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust colorbalance %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i)));
+    }
+
+    private void onSeekHaze(int index, int progress) {
+        progresses[index] = progress;
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@style haze %.2f %.2f %.2f %.2f %.2f ", getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i)));
+    }
+
+    private static String[] TYPES = {"overlay", "colordodge", "pinlight", "ol", "screen"};
+
+    private void onSeekPixBlend(int index, int progress) {
+        progresses[index] = progress;
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@adjust saturation %.2f @pixblend %s %.2f %.2f %.2f %d ", getPercent(i++), TYPES[progresses[1] / 20 % TYPES.length], getPercent(i++), getPercent(i++), getPercent(i++), getPercent(i, 40)));
+    }
+
+    private void onSeekCurve(int index, int progress) {
+        progresses[index] = progress;
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@curve R(%d, %d)(%d, %d)(%d, %d) ", getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255), getPercent(i++, 255)));
+    }
+
+    private void onSeekBeautify(int index, int progress) {
+        progresses[index] = progress;
+        int i = 0;
+        mPlayerView.setFilterWithConfig(String.format(Locale.CHINA, "@beautify face %d %d, %d ", getPercent(i++, 2), getPercent(i++, 1000), getPercent(i++, 1000)));
+    }
+
+    View.OnClickListener galleryBtnClickListener = new View.OnClickListener() {
+
+        @Override
+        public void onClick(final View view) {
+            Intent videoPickerIntent = new Intent(Intent.ACTION_GET_CONTENT);
+            videoPickerIntent.setType("video/*");
+            startActivityForResult(videoPickerIntent, REQUEST_CODE_PICK_VIDEO);
+        }
+    };
+
+    @Override
+    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
+        switch (requestCode) {
+            case REQUEST_CODE_PICK_VIDEO:
+                if (resultCode == RESULT_OK) {
+
+                    mPlayerView.setVideoUri(data.getData(), new VideoPlayerGLSurfaceView.PlayPreparedCallback() {
+                        @Override
+                        public void playPrepared(MediaPlayer player) {
+                            Log.i(Common.LOG_TAG, "The video is prepared to play");
+                            player.start();
+                        }
+                    }, playCompletionCallback);
+                }
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        Log.i(VideoPlayerGLSurfaceView.LOG_TAG, "activity onPause...");
+        mPlayerView.release();
+        mPlayerView.onPause();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        mPlayerView.onResume();
+    }
+
+    @Override
+    protected Fragment initFragment() {
+        return new FgtChooseEditList();
+    }
+}

+ 21 - 0
media/app/src/main/java/com/kfzs/cfyl/media/activity/MainActivity.java

@@ -0,0 +1,21 @@
+package com.kfzs.cfyl.media.activity;
+
+import com.kfzs.cfyl.media.BaseActivity;
+import com.kfzs.cfyl.media.R;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class MainActivity extends BaseActivity {
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.main_activity;
+    }
+
+    @Override
+    public void initView() {
+
+    }
+}

+ 11 - 0
media/app/src/main/java/com/kfzs/cfyl/media/api/Filterble.java

@@ -0,0 +1,11 @@
+package com.kfzs.cfyl.media.api;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ * 可以选择滤镜
+ */
+public interface Filterble {
+    void setFilter(IFilter item);
+    void setFilterIntensity(float intensity);
+}

+ 11 - 0
media/app/src/main/java/com/kfzs/cfyl/media/api/IFilter.java

@@ -0,0 +1,11 @@
+package com.kfzs.cfyl.media.api;
+
+/**
+ * Created by realicing on 2018/12/3.
+ * realicing@sina.com
+ * 滤镜
+ */
+public interface IFilter {
+    String getName();//滤镜名称
+    String getConfig();//滤镜的配置
+}

+ 10 - 0
media/app/src/main/java/com/kfzs/cfyl/media/api/IdChooser.java

@@ -0,0 +1,10 @@
+package com.kfzs.cfyl.media.api;
+
+/**
+ * Created by realicing on 2018/12/10.
+ * realicing@sina.com
+ * 主题选择
+ */
+public interface IdChooser {
+    void onSelectId(int id);
+}

+ 66 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/BeautifyFilter.java

@@ -0,0 +1,66 @@
+package com.kfzs.cfyl.media.bean;
+
+
+import com.kfzs.cfyl.media.api.IFilter;
+
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ * 美化
+ */
+public class BeautifyFilter implements IFilter {
+
+    private String name;
+
+    public BeautifyFilter(String name) {
+        this.name = name;
+    }
+
+    private int type = 1;
+    private int width = 480;
+    private int height = 640;
+
+    public int getType() {
+        return type;
+    }
+
+    public BeautifyFilter setType(int type) {
+        this.type = type;
+        return this;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public BeautifyFilter setWidth(int width) {
+        this.width = width;
+        return this;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public BeautifyFilter setHeight(int height) {
+        this.height = height;
+        return this;
+    }
+
+    public BeautifyFilter setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getConfig() {
+        return String.format(Locale.CHINA, "@beautify face %d %d %d", type, width, height);
+    }
+}

+ 198 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/ColorBalanceFilter.java

@@ -0,0 +1,198 @@
+package com.kfzs.cfyl.media.bean;
+
+
+import com.kfzs.cfyl.media.api.IFilter;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/12/3.
+ * realicing@sina.com
+ * ColorBalance滤镜
+ */
+public class ColorBalanceFilter implements IFilter {
+    private String name;
+    private float red;//范围-1 到 1
+    private float green;//范围-1 到 1
+    private float blue;//范围-1 到 1
+
+    public ColorBalanceFilter(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public float getRed() {
+        return red;
+    }
+
+    public ColorBalanceFilter setRed(float red) {
+        this.red = red;
+        return this;
+    }
+
+    public float getGreen() {
+        return green;
+    }
+
+    public ColorBalanceFilter setGreen(float green) {
+        this.green = green;
+        return this;
+    }
+
+    public float getBlue() {
+        return blue;
+    }
+
+    public ColorBalanceFilter setBlue(float blue) {
+        this.blue = blue;
+        return this;
+    }
+
+    public ColorBalanceFilter setColor(int color) {
+        this.red = (color & 0xff0000) >> 16;
+        this.green = (color & 0x00ff00) >> 8;
+        this.blue = (color & 0x0000ff);
+        return this;
+    }
+
+    public ColorBalanceFilter setColor(String color) {
+        return setColor(Integer.parseInt(color.replace("#", ""), 16));
+    }
+
+    @Override
+    public String getConfig() {
+        return String.format(Locale.CHINA, "@adjust colorbalance %.2f %.2f %.2f", red, green, blue);
+    }
+
+
+    public IFilter setYellow(int yellow) {
+        this.red = yellow;
+        this.green = yellow;
+        return this;
+    }
+
+    //添加默认滤镜列表
+    public static void addDefaultFilterList(List<IFilter> filterList) {
+        filterList.addAll(getDefaultFilterList());
+    }
+
+    //添加默认滤镜列表
+    public static List<IFilter> getDefaultFilterList() {
+        List<IFilter> filterList = new ArrayList<>();
+        filterList.add(new ColorBalanceFilter("红色").setRed(255));
+        filterList.add(new ColorBalanceFilter("绿色").setGreen(255));
+        filterList.add(new ColorBalanceFilter("蓝色").setBlue(255));
+        filterList.add(new ColorBalanceFilter("黄色").setYellow(255));
+        filterList.add(new ColorBalanceFilter("品红").setRed(255).setBlue(255));
+        filterList.add(new ColorBalanceFilter("青色").setGreen(255).setBlue(255));
+        return filterList;
+    }
+}
+//    name("", "@adjust hsl 0.02 -0.31 -0.17 @curve R(0, 28)(23, 45)(117, 148)(135, 162)G(0, 8)(131, 152)(255, 255)B(0, 17)(58, 80)(132, 131)(127, 131)(255, 225)"),
+//    name("", "@adjust saturation 0 @adjust level 0 0.83921 0.8772"),
+//    name("", "@adjust saturation 0 @curve R(0, 49)(16, 44)(34, 56)(74, 120)(120, 185)(151, 223)(255, 255)G(0, 46)(34, 73)(85, 129)(111, 164)(138, 192)(170, 215)(255, 255)B(0, 77)(51, 101)(105, 143)(165, 182)(210, 213)(250, 229)"),
+//    name("", "@vigblend mix 10 10 30 255 91 0 1.0 0.5 0.5 3 @curve R(0, 31)(35, 75)(81, 139)(109, 174)(148, 207)(255, 255)G(0, 24)(59, 88)(105, 146)(130, 171)(145, 187)(180, 214)(255, 255)B(0, 96)(63, 130)(103, 157)(169, 194)(255, 255)"),
+//    name("", "@curve R(0, 64)(16, 13)(58, 128)(108, 109)(162, 223)(255, 255)G(0, 30)(22, 35)(42, 58)(56, 86)(70, 119)(130, 184)(189, 212)B(6, 36)(76, 157)(107, 192)(173, 229)(255, 255)"),
+//    name("", "@adjust saturation 0 @curve R(0, 68)(10, 72)(42, 135)(72, 177)(98, 201)(220, 255)G(0, 29)(12, 30)(57, 127)(119, 203)(212, 255)(254, 239)B(0, 36)(54, 118)(66, 141)(119, 197)(155, 215)(255, 254)"),
+//    name("", "@curve R(42, 2)(53, 52)(80, 102)(100, 123)(189, 196)(255, 255)G(55, 74)(75, 98)(95, 114)(177, 197)(203, 212)(221, 220)(229, 234)(240, 249)B(0, 132)(81, 188)(180, 251)"),
+//    name("", "@adjust saturation 0 @curve R(9, 13)(37, 13)(63, 23)(81, 43)(91, 58)(103, 103)(159, 239)(252, 242)G(3, 20)(29, 20)(56, 19)(77, 37)(107, 108)(126, 184)(137, 217)(150, 248)(182, 284)(255, 255)B(45, 17)(78, 51)(96, 103)(131, 202)(255, 255)"),
+//    name("", "@curve R(0, 0)(135, 147)(255, 255)G(0, 0)(135, 147)(255, 255)B(0, 0)(135, 147)(255, 255)  @adjust saturation 0.71 @adjust brightness -0.05 @curve R(19, 0)(45, 36)(88, 90)(130, 125)(200, 170)(255, 255)G(18, 0)(39, 26)(71, 74)(147, 160)(255, 255)B(0, 0)(77, 58)(136, 132)(255, 204)"),
+//    name("", "@curve R(81, 3)(161, 129)(232, 253)G(91, 0)(164, 136)(255, 225)B(76, 0)(196, 162)(255, 225)"),
+//    name("", "@curve R(9, 0)(49, 62)(124, 155)(218, 255)G(10, 0)(30, 33)(137, 169)(223, 255)B(10, 0)(37, 45)(96, 122)(150, 182)(221, 255)"),
+//    name("", "@curve R(0, 0)(120, 96)(165, 255)G(90, 0)(131, 145)(172, 255)B(77, 0)(165, 167)(255, 255)"),
+//    name("", "@curve R(16, 0)(60, 45)(124, 124)(214, 255)G(18, 2)(91, 81)(156, 169)(213, 255)B(16, 0)(85, 74)(158, 171)(211, 255) @curve R(17, 0)(144, 150)(214, 255)G(16, 0)(61, 47)(160, 172)(215, 255)B(21, 2)(131, 135)(213, 255)"),
+//    name("", "@curve R(2, 2)(16, 30)(72, 112)(135, 185)(252, 255)G(2, 1)(30, 42)(55, 84)(157, 207)(238, 249)B(1, 0)(26, 17)(67, 106)(114, 165)(231, 250)"),
+//    name("", "@curve R(0, 0)(69, 93)(126, 160)(210, 232)(255, 255)G(0, 0)(36, 47)(135, 169)(250, 254)B(0, 0)(28, 30)(107, 137)(147, 206)(255, 255)"),
+//    name("", "@curve R(9, 0)(26, 7)(155, 108)(194, 159)(255, 253)G(9, 0)(50, 19)(218, 194)(255, 255)B(0, 0)(29, 9)(162, 116)(218, 194)(255, 255)"),
+//    name("", "@curve R(14, 0)(51, 42)(135, 138)(191, 202)(234, 255)G(11, 6)(78, 77)(178, 185)(242, 250)B(11, 0)(22, 10)(72, 60)(171, 162)(217, 209)(255, 255)"),
+//    name("", "@curve R(5, 8)(36, 51)(115, 145)(201, 220)(255, 255)G(6, 9)(67, 83)(169, 190)(255, 255)B(3, 3)(55, 60)(177, 190)(255, 255)"),
+//    name("", "@curve R(4, 4)(38, 38)(146, 146)(201, 202)(255, 255)G(0, 0)(80, 74)(192, 187)(255, 255)B(0, 0)(58, 58)(183, 184)(255, 255)"),
+//    name("", "@curve R(33, 0)(70, 32)(146, 143)(185, 204)(255, 255)G(22, 0)(103, 71)(189, 219)(255, 252)B(10, 0)(54, 29)(93, 66)(205, 220)(255, 255)"),
+//    name("", "@curve R(17, 0)(37, 18)(75, 52)(238, 255)G(16, 0)(53, 32)(113, 92)(236, 255)B(16, 0)(80, 57)(171, 164)(235, 255)"),
+//    name("", "@curve R(0, 4)(39, 103)(134, 223)(242, 255)G(0, 3)(31, 85)(68, 155)(131, 255)(219, 255)B(0, 3)(42, 110)(114, 207)(255, 255)"),
+//    name("", "@curve R(15, 0)(45, 37)(92, 103)(230, 255)G(19, 0)(34, 22)(138, 158)(228, 252)B(19, 0)(74, 63)(159, 166)(230, 255)"),
+//    name("", "@curve R(3, 0)(23, 29)(83, 116)(167, 206)(255, 255)G(5, 0)(56, 64)(160, 189)(255, 255)B(3, 0)(48, 49)(142, 167)(248, 255)"),
+//    name("", "@colormul mat 0.34 0.48 0.22 0.34 0.48 0.22 0.34 0.48 0.22 @curve R(0, 0)(9, 10)(47, 38)(87, 69)(114, 92)(134, 116)(175, 167)(218, 218)(255, 255)G(40, 0)(45, 14)(58, 34)(74, 55)(125, 118)(192, 205)(255, 255)B(0, 0)(15, 16)(37, 31)(71, 55)(108, 88)(159, 151)(204, 201)(255, 255)"),
+//    name("", "@colormul mat 0.34 0.48 0.22 0.34 0.48 0.22 0.34 0.48 0.22 @curve R(0, 29)(20, 48)(83, 103)(164, 166)(255, 239)G(0, 30)(30, 61)(66, 94)(151, 160)(255, 241)B(2, 48)(82, 93)(166, 143)(255, 199)"),
+//    name("", "@adjust hsv -1 -1 -1 -1 -1 -1"),
+//    name("", "@curve R(4, 35)(65, 82)(117, 148)(153, 208)(206, 255)G(13, 5)(74, 78)(109, 144)(156, 201)(250, 250)B(6, 37)(93, 104)(163, 184)(238, 222)(255, 237) @adjust hsv -0.2 -0.2 -0.44 -0.2 -0.2 -0.2"),
+//    name("", "@curve R(40, 40)(86, 148)(255, 255)G(0, 28)(67, 140)(142, 214)(255, 255)B(0, 100)(103, 176)(195, 174)(255, 255) @adjust hsv 0.32 0 -0.5 -0.2 0 -0.4"),
+//    name("", "@adjust hsv 0.3 -0.5 -0.3 0 0.35 -0.2 @curve R(0, 0)(111, 163)(255, 255)G(0, 0)(72, 56)(155, 190)(255, 255)B(0, 0)(103, 70)(212, 244)(255, 255)"),
+//    name("", "@adjust hsv -0.5 -0.5 -0.5 -0.5 -0.5 -0.5 @curve R(0, 0)(129, 148)(255, 255)G(0, 0)(92, 77)(175, 189)(255, 255)B(0, 0)(163, 144)(255, 255)"),
+//    name("", "@adjust hsv -0.4 -0.64 -1.0 -0.4 -0.88 -0.88 @curve R(0, 0)(119, 160)(255, 255)G(0, 0)(83, 65)(163, 170)(255, 255)B(0, 0)(147, 131)(255, 255)"),
+//    name("", "@adjust hsv -0.8 0 -0.8 -0.8 0.5 -0.8 @pixblend ol 0.78036 0.70978 0.09018 1 28"),
+//    name("", "@adjust hsv -0.7 0.5 -0.7 -0.7 0 0 @pixblend ol 0.2941 0.55292 0.06665 1 25"),
+//    name("", "@adjust hsv -0.7 0.5 -0.7 -0.7 -0.7 0.5 @pixblend ol 0.07059 0.60391 0.57254 1 25"),
+//    name("", "@adjust hsv -0.7 -0.7 0.5 -0.7 -0.7 0.5 @pixblend ol 0.243 0.07059 0.59215 1 25"),
+//    name("", "@curve R(5, 49)(85, 173)(184, 249)G(23, 35)(65, 76)(129, 145)(255, 199)B(74, 69)(158, 107)(255, 126)"),
+//    name("", "@curve R(18, 0)(67, 63)(104, 152)(128, 255)G(23, 4)(87, 106)(132, 251)B(17, 0)(67, 63)(108, 174)(128, 251)"),
+//    name("", "@curve R(40, 162)(108, 186)(142, 208)(193, 227)(239, 249)G(13, 7)(72, 87)(124, 150)(197, 206)(255, 255)B(8, 22)(57, 97)(112, 147)(184, 204)(255, 222)"),
+//    name("", "@curve R(39, 0)(93, 61)(130, 136)(162, 193)(208, 255)G(41, 0)(92, 61)(128, 133)(164, 197)(200, 250)B(0, 23)(125, 127)(255, 230)"),
+//    name("", "@curve R(48, 56)(82, 129)(130, 206)(214, 255)G(7, 37)(64, 111)(140, 190)(232, 220)B(2, 97)(114, 153)(229, 172)"),
+//    name("", "@curve R(0, 4)(255, 244)G(0, 0)(255, 255)B(0, 84)(255, 194)"),
+//    name("", "@curve R(15, 0)(92, 133)(255, 234)G(0, 20)(105, 128)(255, 255)B(0, 0)(120, 132)(255, 214)"),
+//    name("", "@curve R(0, 0)(35, 71)(153, 197)(255, 255)G(0, 15)(16, 36)(109, 132)(255, 255)B(0, 23)(181, 194)(255, 230)"),
+//    name("", "@curve R(0, 0)(43, 77)(56, 104)(100, 166)(255, 255)G(0, 0)(35, 53)(255, 255)B(0, 0)(110, 123)(255, 212)"),
+//    name("", "@curve R(0, 0)(69, 63)(105, 138)(151, 222)(255, 255)G(0, 0)(67, 51)(135, 191)(255, 255)B(0, 0)(86, 76)(150, 212)(255, 255)"),
+//    name("", "@adjust saturation 0.7 @pixblend screen 1 0.243 0.69 1 30"),
+//    name("", "@adjust saturation 0.7 @pixblend screen 0.8112 0.243 1 1 40"),
+//    name("", "@curve B(0, 0)(70, 87)(140, 191)(255, 255) @pixblend pinlight 0.247 0.49 0.894 1 20"),
+//    name("", "@curve G(0, 0)(101, 127)(255, 255) @pixblend colordodge 0.937 0.482 0.835 1 20"),
+//    name("", "@curve R(0, 0)(149, 145)(255, 255)G(0, 0)(149, 145)(255, 255)B(0, 0)(149, 145)(255, 255) @pixblend colordodge 0.937 0.482 0.835 1 20"),
+//    name("", "@curve R(0, 0)(152, 183)(255, 255)G(0, 0)(161, 133)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve R(0, 0)(96, 61)(154, 177)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve R(0, 0)(71, 74)(164, 165)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve B(0, 0)(68, 72)(149, 184)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@curve G(0, 0)(144, 166)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@curve R(0, 0)(71, 74)(164, 165)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@adjust saturation 0.7 @pixblend screen 1 0.243 0.69 1 30"),
+//    name("", "@adjust saturation 0.7 @pixblend screen 0.8112 0.243 1 1 40"),
+//    name("", "@curve B(0, 0)(70, 87)(140, 191)(255, 255) @pixblend pinlight 0.247 0.49 0.894 1 20"),
+//    name("", "@curve G(0, 0)(101, 127)(255, 255) @pixblend colordodge 0.937 0.482 0.835 1 20"),
+//    name("", "@curve R(0, 0)(149, 145)(255, 255)G(0, 0)(149, 145)(255, 255)B(0, 0)(149, 145)(255, 255) @pixblend colordodge 0.937 0.482 0.835 1 20"),
+//    name("", "@curve R(0, 0)(152, 183)(255, 255)G(0, 0)(161, 133)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve R(0, 0)(96, 61)(154, 177)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve R(0, 0)(71, 74)(164, 165)(255, 255) @pixblend overlay 0.357 0.863 0.882 1 40"),
+//    name("", "@curve B(0, 0)(68, 72)(149, 184)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@curve G(0, 0)(144, 166)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@curve R(0, 0)(71, 74)(164, 165)(255, 255) @pixblend screen 0.94118 0.29 0.29 1 20"),
+//    name("", "@style haze 0.5 -0.14 1 0.8 1"),
+//    name("", "@style max"),
+//    name("", "@style min"),
+//    name("", "@adjust level 0.66 0.23 0.44"),
+//    name("", "@adjust colorbalance 0.99 0.52 -0.31"),
+//    name("", "@adjust sharpen 10 1.5"),
+//    name("", "@adjust shadowhighlight -200 200"),
+//    name("", "@adjust exposure 0.98"),
+//    name("", "@curve R(0, 0)(63, 101)(200, 84)(255, 255)G(0, 0)(86, 49)(180, 183)(255, 255)B(0, 0)(19, 17)(66, 41)(97, 92)(137, 156)(194, 211)(255, 255)RGB(0, 0)(82, 36)(160, 183)(255, 255)"),
+//    name("", "@vigblend overlay 255 0 0 255 100 0.12 0.54 0.5 0.5 3"),
+//    name("", "@style halftone 1.2"),
+//    name("", "#unpack @style emboss 1 2 2"),
+//    name("", "@adjust level 0.31 0.54 0.13"),
+//    name("", "@style edge 1 2 @curve RGB(0, 255)(255, 0) @adjust saturation 0 @adjust level 0.33 0.71 0.93"),
+//    name("", "@style edge 1 2 @curve RGB(0, 255)(255, 0)"),
+//    name("", "@style edge 1 2"),
+//    name("", "@style crosshatch 0.01 0.003"),
+//    name("", "@beautify bilateral 100 3.5 2"),
+//    name("", "#unpack @krblend darken hehe.jpg 100"),
+//    name("", "#unpack @krblend add hehe.jpg 100"),
+//    name("", "#unpack @krblend ol hehe.jpg 100"),
+//    name("", "#unpack @krblend sr hehe.jpg 100"),
+//    name("", "#unpack @style sketch 0.9"),
+//    name("", "@dynamic wave 0.5"),
+//    name("", "#unpack @dynamic wave 1"),
+//    name("", "@blur lerp 1"),
+//    name("", "#unpack @blur lerp 0.75"),
+//    name("", "@adjust lut wildbird.png"),
+//    name("", "@adjust lut soft_warming.png"),
+//    name("", "@adjust lut late_sunset.png"),
+//    name("", "@adjust lut foggy_night.png"),
+//    name("", "@adjust lut filmstock.png"),
+//    name("", "@adjust lut edgy_amber.png"),
+//    name("", "@beautify face 1 480 640"),
+//    name("", "@curve RGB(0,255)(255,0) @style cm mapping0.jpg 80 80 8 3"),

+ 37 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/Filter.java

@@ -0,0 +1,37 @@
+package com.kfzs.cfyl.media.bean;
+
+
+import com.kfzs.cfyl.media.api.IFilter;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ */
+public class Filter implements IFilter {
+    private String name;
+    private String config = "";
+
+    public Filter(String name) {
+        this.name = name;
+    }
+
+    public Filter setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public Filter setConfig(String config) {
+        this.config = config;
+        return this;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getConfig() {
+        return config;
+    }
+}

+ 119 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/Lp.java

@@ -0,0 +1,119 @@
+package com.kfzs.cfyl.media.bean;
+
+/**
+ * Created by realicing on 2018/11/13.
+ * realicing@sina.com
+ * 配置layoutParams,配置LayoutParamsUtil使用
+ */
+public class Lp {
+    //不用设置标识
+    public static final int NONE = -101;
+    private int leftMargin = NONE;
+    private int rightMargin = NONE;
+    private int topMargin = NONE;
+    private int bottomMargin = NONE;
+    private int width = NONE;
+    private int height = NONE;
+    private float per = 1.0f;
+
+    public Lp() {
+    }
+
+    public Lp(float per) {
+        this.per = per;
+    }
+
+    public static int getNONE() {
+        return NONE;
+    }
+
+    public int getLeftMargin() {
+        return leftMargin;
+    }
+
+    public Lp setLeftMargin(int leftMargin) {
+        this.leftMargin = (int) (leftMargin * per);
+        return this;
+    }
+
+    public int getRightMargin() {
+        return rightMargin;
+    }
+
+    public Lp setRightMargin(int rightMargin) {
+        this.rightMargin = (int) (rightMargin * per);
+        return this;
+    }
+
+    public int getTopMargin() {
+        return topMargin;
+    }
+
+    public Lp setTopMargin(int topMargin) {
+        this.topMargin = (int) (topMargin * per);
+        return this;
+    }
+
+    public int getBottomMargin() {
+        return bottomMargin;
+    }
+
+    public Lp setBottomMargin(int bottomMargin) {
+        this.bottomMargin = (int) (bottomMargin * per);
+        return this;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public Lp setWidth(int width) {
+        this.width = (int) (width * per);
+        return this;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public Lp setHeight(int height) {
+        this.height = (int) (height * per);
+        return this;
+    }
+
+    public Lp addLeftMargin(float mx) {
+        int addMargin = (int) (per * mx);
+        switch (leftMargin) {
+            case NONE:
+                leftMargin = addMargin;
+                break;
+            default:
+                leftMargin += addMargin;
+                break;
+        }
+        return this;
+    }
+
+    public Lp setLrMargin(int margin) {
+        margin = (int) (margin * per);
+        this.leftMargin = margin;
+        this.rightMargin = margin;
+        return this;
+    }
+
+    public Lp setTbMargin(int margin) {
+        margin = (int) (margin * per);
+        this.topMargin = margin;
+        this.bottomMargin = margin;
+        return this;
+    }
+
+    public Lp setMargin(int margin) {
+        margin = (int) (margin * per);
+        this.topMargin = margin;
+        this.bottomMargin = margin;
+        this.leftMargin = margin;
+        this.rightMargin = margin;
+        return this;
+    }
+}

+ 48 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/Size.java

@@ -0,0 +1,48 @@
+package com.kfzs.cfyl.media.bean;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ */
+public class Size {
+    private int width;
+    private int height;
+    private int x;
+    private int y;
+
+    public int getWidth() {
+        return width;
+    }
+
+    public Size setWidth(int width) {
+        this.width = width;
+        return this;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public Size setHeight(int height) {
+        this.height = height;
+        return this;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public Size setX(int x) {
+        this.x = x;
+        return this;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public Size setY(int y) {
+        this.y = y;
+        return this;
+    }
+}

+ 49 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/VideoFrame.java

@@ -0,0 +1,49 @@
+package com.kfzs.cfyl.media.bean;
+
+/**
+ * Created by realicing on 2018/12/10.
+ * realicing@sina.com
+ * 视频帧
+ */
+public class VideoFrame {
+    private String videoPath;
+    private int width;
+    private int height;
+    private long atTime;
+
+    public String getVideoPath() {
+        return videoPath;
+    }
+
+    public VideoFrame setVideoPath(String videoPath) {
+        this.videoPath = videoPath;
+        return this;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public VideoFrame setWidth(int width) {
+        this.width = width;
+        return this;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public VideoFrame setHeight(int height) {
+        this.height = height;
+        return this;
+    }
+
+    public long getAtTime() {
+        return atTime;
+    }
+
+    public VideoFrame setAtTime(long atTime) {
+        this.atTime = atTime;
+        return this;
+    }
+}

+ 59 - 0
media/app/src/main/java/com/kfzs/cfyl/media/bean/WaveFilter.java

@@ -0,0 +1,59 @@
+package com.kfzs.cfyl.media.bean;
+
+import android.text.TextUtils;
+
+import com.kfzs.cfyl.media.api.IFilter;
+
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ * 波浪滤镜
+ */
+public class WaveFilter implements IFilter {
+
+    private String name;
+    private String type = "#unpack";
+
+    public WaveFilter(String name) {
+        this.name = name;
+    }
+    private float percent = 0.5f;
+
+    public float getPercent() {
+        return percent;
+    }
+
+    public WaveFilter setPercent(float percent) {
+        this.percent = percent;
+        return this;
+    }
+
+    public WaveFilter setName(String name) {
+        this.name = name;
+        return this;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public WaveFilter setType(String type) {
+        this.type = type;
+        return this;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getConfig() {
+        if(TextUtils.isEmpty(type)){
+            return String.format(Locale.CHINA, "@dynamic wave %.1f", percent);
+        }
+        return String.format(Locale.CHINA, "%s @dynamic wave %.1f", type , percent);
+    }
+}

+ 411 - 0
media/app/src/main/java/com/kfzs/cfyl/media/customview/VideoFramesView.java

@@ -0,0 +1,411 @@
+package com.kfzs.cfyl.media.customview;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.media.MediaMetadataRetriever;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder;
+import com.bumptech.glide.request.RequestOptions;
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.bean.VideoFrame;
+import com.kfzs.cfyl.media.glide.VideoFrameTransform;
+import com.kfzs.cfyl.media.util.VideoUtil;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import rx.functions.Action1;
+
+
+/**
+ * Created by realicing on 2018/11/29.
+ * realicing@sina.com
+ * 显示本地视频文件对应的视频帧
+ */
+public class VideoFramesView extends RelativeLayout {
+    public VideoFramesView(Context context) {
+        super(context);
+        initView();
+    }
+
+    public VideoFramesView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        initView();
+    }
+
+    public VideoFramesView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        initView();
+    }
+
+    private RecyclerView recyclerView;
+    private View line_start;
+    private View line_end;
+
+    private void initView() {
+        LayoutInflater.from(getContext()).inflate(R.layout.custom_video_frames_view, this, true);
+        recyclerView = findViewById(R.id.recyclerView);
+        line_start = findViewById(R.id.line_start);
+        line_end = findViewById(R.id.line_end);
+        line_start.setOnTouchListener(new OnTouchListener() {
+            private float lastEventX;
+
+            @SuppressLint("ClickableViewAccessibility")
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                float maxX = line_end.getX();
+                float minX = maxX - (firstEndX - firstStartX);//结束位置 - 可以设置的长度
+                switch (event.getAction()) {
+                    case MotionEvent.ACTION_DOWN:
+                        lastEventX = event.getX();
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        float mx = Math.max(firstStartX, view.getX() + event.getX() - lastEventX);
+                        if (mx > maxX)
+                            mx = maxX;
+                        if (mx < minX) {
+                            maxX += mx - minX;
+                            line_end.setX(maxX);
+                            view.setX(mx);
+                        } else {
+                            view.setX(mx);
+                        }
+                        if (onTimeChangeListener != null) {
+                            onTimeChangeListener.call((maxX - mx) * video.getDuration() / (rvW - lineW));
+                        }
+                        break;
+                    case MotionEvent.ACTION_UP:
+                        break;
+                    case MotionEvent.ACTION_CANCEL:
+                        break;
+                }
+                view.invalidate();
+                return true;
+            }
+        });
+        line_end.setOnTouchListener(new OnTouchListener() {
+            private float lastEventX;
+
+            @SuppressLint("ClickableViewAccessibility")
+            @Override
+            public boolean onTouch(View view, MotionEvent event) {
+                float minX = line_start.getX();
+                float maxX = firstEndX - firstStartX + minX;
+                float endX = firstStartX + rvW - lineW;
+                switch (event.getAction()) {
+                    case MotionEvent.ACTION_DOWN:
+                        lastEventX = event.getX();
+                        break;
+                    case MotionEvent.ACTION_MOVE:
+                        float mx = Math.min(view.getX() + event.getX() - lastEventX, endX);
+                        if (mx < minX)
+                            mx = minX;
+                        if (mx > maxX) {
+                            minX += mx - maxX;
+                            line_start.setX(minX);
+                            view.setX(mx);
+                        } else {
+                            view.setX(mx);
+                        }
+                        if (onTimeChangeListener != null) {
+                            onTimeChangeListener.call((mx - minX) * video.getDuration() / (rvW - lineW));
+                        }
+                        break;
+                    case MotionEvent.ACTION_UP:
+                        break;
+                    case MotionEvent.ACTION_CANCEL:
+                        break;
+                }
+                view.invalidate();
+                return true;
+            }
+        });
+    }
+
+    //开头线的进度
+    public float getStartPercent() {
+        if (line_start != null && recyclerView != null) {
+            return (line_start.getX() - firstStartX) / (rvW - lineW);
+        }
+        return 0;
+    }
+
+    private float firstStartX;//初始时开头的x位置
+    private float firstEndX;//初始时结尾的x位置
+    private int lineW;//开头与结尾线的宽度
+    private int rvW;//图片列表的长度,减去lineW后==总进度的长度
+
+    //结尾线的进度
+    public float getEndPercent() {
+        if (line_end != null && recyclerView != null) {
+            return 1.0f - ((firstStartX + rvW - lineW - line_end.getX()) / (rvW - lineW));
+        }
+        return 0;
+    }
+
+    //总的进度
+    public float getPercent() {
+        if (line_end != null && recyclerView != null) {
+            return (line_end.getX() - line_start.getX()) / (rvW - lineW);
+        }
+        return 0;
+    }
+
+    public String getLineInfo() {
+        return String.format(Locale.CHINA, "firstStartX = %f, firstEndX = %f, startX = %f, endX = %f, lineW = %d, rvW = %d, startPercent = %f, endPercent = %f, percent = %f", firstStartX, firstEndX, line_start.getX(), line_end.getX(), line_end.getWidth(), recyclerView.getWidth(), getStartPercent(), getEndPercent(), getPercent());
+    }
+
+    private Video video;
+
+    /**
+     * 显示视频帧图片列表
+     *
+     * @param data 视频数据,包括地址与时长,宽高等
+     * @return
+     */
+    public VideoFramesView initVideo(Video data) {
+        if (data == null || data.getFilePath() == null) {
+            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoPath is null");
+            return this;
+        }
+        File videoFile = new File(data.getFilePath());
+        if (!videoFile.exists()) {
+            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile not exists");
+            return this;
+        }
+        if (!videoFile.canRead()) {
+            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "videoFile cant read");
+            return this;
+        }
+        if (data.getDuration() < 1) {
+            LogUtil.println(VideoFramesView.class.getSimpleName(), "showList", "error", "duration < 1");
+            return this;
+        }
+        this.video = data;
+        return this;
+    }
+
+    private List<Bitmap> bitmapList = new ArrayList<>();
+
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList1(final Activity activity) {
+        final int size = 10;
+        long duration = video.getDuration();
+        final long per = duration * 1000L / size;
+        int max = 20;
+        int width = max, height = max;
+        if (video.getWidth() > video.getHeight()) {
+            width = max * video.getWidth() / video.getHeight();
+        } else {
+            height = max * video.getHeight() / video.getWidth();
+        }
+        for (int i = 0; i < size; i++) {
+            final int finalWidth = width;
+            final int finalHeight = height;
+            final int finalI = i;
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    Bitmap bitmap = VideoUtil.getVideoFrameBitmap(video, finalI * per, finalWidth, finalHeight);
+                    bitmapList.add(bitmap);
+                    activity.runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (recyclerView.getAdapter() != null)
+                                recyclerView.getAdapter().notifyDataSetChanged();
+                        }
+                    });
+                }
+            }).start();
+        }
+        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), size));
+        BaseQuickAdapter<Bitmap, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<Bitmap, BaseViewHolder>(R.layout.item_iv_mh, bitmapList) {
+            @Override
+            protected void convert(BaseViewHolder helper, Bitmap item) {
+                ImageView imageView = helper.getView(R.id.item_iv);
+                imageView.setImageBitmap(item);
+            }
+        };
+        recyclerView.setAdapter(baseQuickAdapter);
+
+        return this;
+    }
+
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList2(final Activity activity) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                final int size = 10;
+                final List<Bitmap> bitmapList = VideoUtil.getVideoFrameBitmapList(video, size);
+                activity.runOnUiThread(new Runnable() {
+                    @Override
+                    public void run() {
+                        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), size));
+                        BaseQuickAdapter<Bitmap, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<Bitmap, BaseViewHolder>(R.layout.item_iv_mh, bitmapList) {
+                            @Override
+                            protected void convert(BaseViewHolder helper, Bitmap item) {
+                                ImageView imageView = helper.getView(R.id.item_iv);
+                                imageView.setImageBitmap(item);
+                            }
+                        };
+                        recyclerView.setAdapter(baseQuickAdapter);
+                    }
+                });
+
+            }
+        }).start();
+
+        return this;
+    }
+
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList3(final Activity activity) {
+        List<VideoFrame> videoFrameList = new ArrayList<>();
+        final int size = 10;
+        long duration = video.getDuration();
+        final long per = duration * 1000L / size;
+        int max = 20;
+        int width = max, height = max;
+        if (video.getWidth() > video.getHeight()) {
+            width = max * video.getWidth() / video.getHeight();
+        } else {
+            height = max * video.getHeight() / video.getWidth();
+        }
+        String path = video.getFilePath();
+        for (int i = 0; i < size; i++) {
+            videoFrameList.add(new VideoFrame().setVideoPath(path).setAtTime(i * per).setWidth(width).setHeight(height));
+        }
+        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), 10));
+        BaseQuickAdapter<VideoFrame, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<VideoFrame, BaseViewHolder>(R.layout.item_iv_mh, videoFrameList) {
+            @Override
+            protected void convert(BaseViewHolder helper, VideoFrame item) {
+                ImageView imageView = helper.getView(R.id.item_iv);
+                Glide.with(activity.getApplicationContext()).load(item.getVideoPath())
+                        .apply(RequestOptions.frameOf(item.getAtTime()).set(VideoBitmapDecoder.FRAME_OPTION, MediaMetadataRetriever.OPTION_CLOSEST).transform(new VideoFrameTransform(item, false)))
+                        .into(imageView);
+            }
+        };
+        recyclerView.setAdapter(baseQuickAdapter);
+
+        return this;
+    }
+    /**
+     * 显示视频帧图片列表
+     */
+    public VideoFramesView showVideoList(final Activity activity) {
+        List<VideoFrame> videoFrameList = new ArrayList<>();
+        final int size = 10;
+        long duration = video.getDuration();
+        final long per = duration * 1000L / size;
+        int max = 20;
+        int width = max, height = max;
+        if (video.getWidth() > video.getHeight()) {
+            width = max * video.getWidth() / video.getHeight();
+        } else {
+            height = max * video.getHeight() / video.getWidth();
+        }
+        String path = video.getFilePath();
+        for (int i = 0; i < size; i++) {
+            videoFrameList.add(new VideoFrame().setVideoPath(path).setAtTime(i * per)
+                    .setWidth(width).setHeight(height)
+                    .setWidth(video.getWidth()).setHeight(video.getHeight())
+            );
+        }
+        recyclerView.setLayoutManager(new GridLayoutManager(activity.getApplicationContext(), size));
+        BaseQuickAdapter<VideoFrame, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<VideoFrame, BaseViewHolder>(R.layout.item_iv_mh, videoFrameList) {
+            @Override
+            protected void convert(BaseViewHolder helper, VideoFrame item) {
+                ImageView imageView = helper.getView(R.id.item_iv);
+                Glide.with(activity.getApplicationContext()).load(R.drawable.qiandao).apply(new RequestOptions().transform(new VideoFrameTransform(item))).into(imageView);
+            }
+        };
+        recyclerView.setAdapter(baseQuickAdapter);
+
+        return this;
+    }
+
+    private Action1<Float> onTimeChangeListener;
+
+    public void setOnTimeChangeListener(Action1<Float> action1) {
+        onTimeChangeListener = action1;
+        postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                firstStartX = line_start.getX();
+                firstEndX = line_end.getX();
+                lineW = line_start.getWidth();
+                rvW = recyclerView.getWidth();
+                long duration = video.getDuration();
+                if (maxVideoDuration > 0) {
+                    if (duration > maxVideoDuration) {
+                        firstEndX = firstStartX + ((maxVideoDuration * 1.0f / duration) * (rvW - lineW));
+                        line_end.setX(firstEndX);
+                    }
+                }
+                onTimeChangeListener.call((float) duration);
+            }
+        }, 100);
+    }
+
+    //开始的时间,单位秒
+    public long getStartPoint() {
+        return (long) (getStartPercent() * video.getDuration());
+    }
+
+    //总共的时长,单位秒
+    public long getLineDuration() {
+        return (long) (getPercent() * video.getDuration());
+    }
+
+    //结束的时间,单位秒
+    public long getEndPoint() {
+        return (long) (getEndPercent() * video.getDuration());
+    }
+
+    //最大剪切视频时长
+    private long maxVideoDuration;
+
+    public VideoFramesView setMaxDuration(long maxVideoDuration) {
+        this.maxVideoDuration = maxVideoDuration;
+        return this;
+    }
+
+    public void onDestroy() {
+        if (recyclerView != null && recyclerView.getAdapter() instanceof BaseQuickAdapter) {
+            for (int i = 0; i < recyclerView.getAdapter().getItemCount(); i++) {
+                Object object = ((BaseQuickAdapter) recyclerView.getAdapter()).getItem(i);
+                if (object instanceof Bitmap) {
+                    try {
+                        ((Bitmap) object).recycle();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+}

+ 56 - 0
media/app/src/main/java/com/kfzs/cfyl/media/dialog/DialogProgress.java

@@ -0,0 +1,56 @@
+package com.kfzs.cfyl.media.dialog;
+
+import android.app.Activity;
+import android.support.v7.app.AlertDialog;
+import android.view.View;
+import android.widget.TextView;
+
+import com.kfzs.cfyl.media.R;
+
+
+/**
+ * 用于百分比对话框(文字在图片中间)
+ * Created by realicing on 2018/08/09.
+ * realicing@sina.com
+ */
+public class DialogProgress {
+    private TextView textView;
+    private AlertDialog alertDialog;
+
+    public static DialogProgress showDialog(final Activity activity) {
+        return showDialog(activity, false);
+    }
+    public static DialogProgress showDialog(Activity activity, boolean cancelable) {
+        DialogProgress dialogShowLoading= new DialogProgress();
+        View view = View.inflate(activity, R.layout.dialog_progress, null);
+        TextView dialog_loading = view.findViewById(R.id.dialog_progress);
+        AlertDialog mAlertDialog = new AlertDialog.Builder(activity, R.style.MyDialogActivityTheme)
+                .setView(view)
+                .create();
+        mAlertDialog.setCancelable(cancelable);
+        dialogShowLoading.setAlertDialog(mAlertDialog);
+        try {
+            mAlertDialog.show();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        dialogShowLoading.setTextView(dialog_loading);
+        return dialogShowLoading;
+    }
+
+    public TextView getTextView() {
+        return textView;
+    }
+
+    public void setTextView(TextView textView) {
+        this.textView = textView;
+    }
+
+    public AlertDialog getAlertDialog() {
+        return alertDialog;
+    }
+
+    public void setAlertDialog(AlertDialog alertDialog) {
+        this.alertDialog = alertDialog;
+    }
+}

+ 39 - 27
app/src/main/java/com/sheep/gamegroup/module/find/fragment/FgtChooseEditList.java

@@ -1,4 +1,4 @@
-package com.sheep.gamegroup.module.find.fragment;
+package com.kfzs.cfyl.media.fragment;
 
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
@@ -8,39 +8,31 @@ import android.widget.SeekBar;
 
 import com.chad.library.adapter.base.BaseQuickAdapter;
 import com.chad.library.adapter.base.BaseViewHolder;
-import com.sheep.gamegroup.model.entity.Lp;
-import com.sheep.gamegroup.module.find.bean.BeautifyFilter;
-import com.sheep.gamegroup.module.find.bean.ColorBalanceFilter;
-import com.sheep.gamegroup.module.find.bean.Filter;
-import com.sheep.gamegroup.module.find.bean.WaveFilter;
-import com.sheep.gamegroup.module.find.util.Filterble;
-import com.sheep.gamegroup.module.find.util.IFilter;
-import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
-import com.sheep.jiuyan.samllsheep.R;
-import com.sheep.jiuyan.samllsheep.SheepApp;
-import com.sheep.jiuyan.samllsheep.base.BaseFragment;
-import com.sheep.jiuyan.samllsheep.utils.G;
+import com.kfzs.cfyl.media.BaseFragment;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.bean.BeautifyFilter;
+import com.kfzs.cfyl.media.bean.ColorBalanceFilter;
+import com.kfzs.cfyl.media.bean.Filter;
+import com.kfzs.cfyl.media.bean.Lp;
+import com.kfzs.cfyl.media.bean.WaveFilter;
+import com.kfzs.cfyl.media.api.Filterble;
+import com.kfzs.cfyl.media.util.G;
+import com.kfzs.cfyl.media.api.IFilter;
+import com.kfzs.cfyl.media.util.LayoutParamsUtil;
+import com.kfzs.cfyl.media.util.ViewUtil;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import butterknife.BindView;
-import butterknife.OnClick;
-
 /**
  * Created by realicing on 2018/12/3.
  * realicing@sina.com
  * 可在该界面选择滤镜、磨皮、大眼瘦脸的效果
  */
 public class FgtChooseEditList extends BaseFragment {
-    @BindView(R.id.fgt_choose_edit_list_ll)
     View fgt_choose_edit_list_ll;
-    @BindView(R.id.fgt_choose_edit_line_v)
     View fgt_choose_edit_line_v;
-    @BindView(R.id.fgt_choose_edit_intensity_sb)
     SeekBar fgt_choose_edit_intensity_sb;
-    @BindView(R.id.recyclerView)
     RecyclerView recyclerView;
 
     @Override
@@ -58,6 +50,29 @@ public class FgtChooseEditList extends BaseFragment {
     private int width;
 
     private void initView() {
+        fgt_choose_edit_list_ll = findViewById(R.id.fgt_choose_edit_list_ll);
+        fgt_choose_edit_line_v = findViewById(R.id.fgt_choose_edit_line_v);
+        fgt_choose_edit_intensity_sb = findViewById(R.id.fgt_choose_edit_intensity_sb);
+
+        findViewById(R.id.fgt_choose_edit_filter_tv).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                onSelectFilter(view);
+            }
+        });
+        findViewById(R.id.fgt_choose_edit_buffing_tv).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                onSelectBuffing(view);
+            }
+        });
+        findViewById(R.id.fgt_choose_edit_warping_tv).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                onSelectWarping(view);
+            }
+        });
+        recyclerView = findViewById(R.id.recyclerView);
         filterList.add(new Filter("原图"));
         ColorBalanceFilter.addDefaultFilterList(filterList);
         filterList.add(new BeautifyFilter("美化").setWidth(G.WIDTH).setHeight(G.HEIGHT));
@@ -74,7 +89,7 @@ public class FgtChooseEditList extends BaseFragment {
         }
 //        filterList.add(new Filter("").setConfig(""));
         width = (G.WIDTH - recyclerView.getPaddingStart() - recyclerView.getPaddingEnd() / 2) / 5;
-        recyclerView.setLayoutManager(new LinearLayoutManager(SheepApp.getInstance(), LinearLayoutManager.HORIZONTAL, false));
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
         recyclerView.setAdapter(new BaseQuickAdapter<IFilter, BaseViewHolder>(R.layout.item_tv_iv, filterList) {
             @Override
             protected void convert(BaseViewHolder helper, final IFilter item) {
@@ -113,21 +128,18 @@ public class FgtChooseEditList extends BaseFragment {
     }
 
     //选择滤镜
-    @OnClick({R.id.fgt_choose_edit_filter_tv})
     public void onSelectFilter(View view) {
 
     }
 
     //选择磨皮
-    @OnClick({R.id.fgt_choose_edit_buffing_tv})
     public void onSelectBuffing(View view) {
-        G.showToast(R.string.coming_soon);
+        G.showToast(getContext(), R.string.coming_soon);
     }
 
     //选择大眼瘦脸
-    @OnClick({R.id.fgt_choose_edit_warping_tv})
     public void onSelectWarping(View view) {
-        G.showToast(R.string.coming_soon);
+        G.showToast(getContext(), R.string.coming_soon);
     }
 
     public static final String EFFECT_CONFIGS[] = {

+ 69 - 0
media/app/src/main/java/com/kfzs/cfyl/media/fragment/FgtDiscoveryTopic.java

@@ -0,0 +1,69 @@
+package com.kfzs.cfyl.media.fragment;
+
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.kfzs.cfyl.media.BaseFragment;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.api.IdChooser;
+import com.kfzs.cfyl.media.util.G;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class FgtDiscoveryTopic extends BaseFragment {
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.common_rv;
+    }
+
+    private RecyclerView recyclerView;
+    @Override
+    public void onViewCreated() {
+        recyclerView = findViewById(R.id.recyclerView);
+        if(list != null){
+            if(recyclerView == null){
+                G.showToast(getContext(), "初始化失败");
+                return;
+            }
+            initView();
+        }
+    }
+
+    public void loadData(ArrayList<String> arrayList) {
+        list = arrayList;
+        if(recyclerView != null)
+            initView();
+    }
+    private BaseQuickAdapter<String, BaseViewHolder> baseQuickAdapter;
+    private void initView(){
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        baseQuickAdapter = getAdapter();
+        baseQuickAdapter.bindToRecyclerView(recyclerView);
+        baseQuickAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+            @Override
+            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+                if(getActivity() instanceof IdChooser){
+                    ((IdChooser) getActivity()).onSelectId(position);
+                }
+            }
+        });
+    }
+    private List<String > list;
+    protected BaseQuickAdapter<String, BaseViewHolder> getAdapter() {
+        return new BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_discovery_topic, list) {
+            @Override
+            protected void convert(BaseViewHolder helper, String item) {
+                helper.setText(R.id.item_discovery_topic_content, item);
+            }
+        };
+    }
+}

+ 50 - 0
media/app/src/main/java/com/kfzs/cfyl/media/glide/CustomGlideModule.java

@@ -0,0 +1,50 @@
+//package com.kfzs.cfyl.media.glide;
+//
+//import android.content.Context;
+//
+//import com.bumptech.glide.Glide;
+//import com.bumptech.glide.GlideBuilder;
+//import com.bumptech.glide.Registry;
+//import com.bumptech.glide.annotation.GlideModule;
+//import com.bumptech.glide.load.engine.cache.LruResourceCache;
+//import com.bumptech.glide.module.AppGlideModule;
+//import com.kfzs.cfyl.media.MediaApp;
+//
+//
+///**
+// * Created by realicing on 2018/12/10.
+// * realicing@sina.com
+// */
+//@GlideModule
+//public class CustomGlideModule extends AppGlideModule {
+//    /**
+//     *  通过GlideBuilder设置默认的结构(Engine,BitmapPool ,ArrayPool,MemoryCache等等).
+//     * @param context
+//     * @param builder
+//     */
+//    @Override
+//    public void applyOptions(Context context, GlideBuilder builder) {
+//
+//        //重新设置内存限制
+//        builder.setMemoryCache(new LruResourceCache(100*1024*1024));
+//
+//    }
+//
+//
+//    @Override
+//    public void registerComponents(Context context, Glide glide, Registry registry) {
+//        super.registerComponents(context, glide, registry);
+//        MediaApp.initGlide(registry);
+//    }
+//
+//    /**
+//     * 清单解析的开启
+//     *
+//     * 这里不开启,避免添加相同的modules两次
+//     * @return
+//     */
+//    @Override
+//    public boolean isManifestParsingEnabled() {
+//        return false;
+//    }
+//}

+ 2 - 2
app/src/main/java/com/sheep/gamegroup/util/glide/FilterTransform.java

@@ -1,11 +1,11 @@
-package com.sheep.gamegroup.util.glide;
+package com.kfzs.cfyl.media.glide;
 
 import android.graphics.Bitmap;
 import android.support.annotation.NonNull;
 
 import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
 import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
-import com.sheep.gamegroup.module.find.util.IFilter;
+import com.kfzs.cfyl.media.api.IFilter;
 
 import org.wysaid.nativePort.CGENativeLibrary;
 

+ 45 - 0
media/app/src/main/java/com/kfzs/cfyl/media/glide/VideoFrameTransform.java

@@ -0,0 +1,45 @@
+package com.kfzs.cfyl.media.glide;
+
+import android.graphics.Bitmap;
+import android.support.annotation.NonNull;
+
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
+import com.kfzs.cfyl.media.bean.VideoFrame;
+import com.kfzs.cfyl.media.util.VideoUtil;
+
+import java.security.MessageDigest;
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ */
+public class VideoFrameTransform extends BitmapTransformation {
+
+    private VideoFrame videoFrame;
+    private boolean isTransform = true;
+
+    public VideoFrameTransform(VideoFrame videoFrame) {
+        super();
+        this.videoFrame = videoFrame;
+    }
+    public VideoFrameTransform(VideoFrame videoFrame, boolean isTransform) {
+        super();
+        this.videoFrame = videoFrame;
+        this.isTransform = isTransform;
+    }
+
+    @Override
+    protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
+        if(isTransform) {
+            return VideoUtil.getVideoFrameBitmap(videoFrame);
+        }
+        return toTransform;
+    }
+
+    @Override
+    public void updateDiskCacheKey(MessageDigest messageDigest) {
+        messageDigest.update((String.format(Locale.CHINA, "%s?w=%d&h=%d&time=%d", videoFrame.getVideoPath(), videoFrame.getWidth(), videoFrame.getHeight(), videoFrame.getAtTime())).getBytes(CHARSET));
+    }
+}

+ 25 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/BitmapUtil.java

@@ -0,0 +1,25 @@
+package com.kfzs.cfyl.media.util;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+
+import com.kfzs.cfyl.media.bean.Size;
+
+
+/**
+ * Created by realicing on 2018/12/4.
+ * realicing@sina.com
+ */
+public class BitmapUtil {
+    public static Bitmap createBigLogo(Bitmap bmp, Size size) {
+        Bitmap result = Bitmap.createBitmap(size.getWidth(), size.getHeight(), Bitmap.Config.ARGB_4444);
+        Canvas canvas = new Canvas(result);
+        Paint paint = new Paint();
+        Matrix matrix = new Matrix();
+        matrix.setTranslate(size.getX(), size.getY());
+        canvas.drawBitmap(bmp, matrix, paint);
+        return result;
+    }
+}

+ 21 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/FileUtil.java

@@ -0,0 +1,21 @@
+package com.kfzs.cfyl.media.util;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class FileUtil {
+
+    /*
+     * Java文件操作 获取文件扩展名
+     * */
+    public static String getExtensionName(String filename) {
+        if ((filename != null) && (filename.length() > 0)) {
+            int dot = filename.lastIndexOf('.');
+            if ((dot > -1) && (dot < (filename.length() - 1))) {
+                return filename.substring(dot + 1);
+            }
+        }
+        return filename;
+    }
+}

+ 33 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/G.java

@@ -0,0 +1,33 @@
+package com.kfzs.cfyl.media.util;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.DisplayMetrics;
+import android.widget.Toast;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class G {
+    public static void showToast(Context context, String msg) {
+        if(context != null)
+            Toast.makeText(context.getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
+    }
+    public static void showToast(Context context, int msg) {
+        if(context != null)
+            Toast.makeText(context.getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
+    }
+
+    public static int HEIGHT = 1280;//屏幕高
+    public static int WIDTH = 720;//屏幕宽
+    public static float DENSITY = 2;//屏幕的Density
+    public static int DENSITY_DPI = 320;//屏幕的Density
+    public static void init(Resources resources) {
+        DisplayMetrics metric = resources.getDisplayMetrics();
+        G.DENSITY = metric.density;
+        G.DENSITY_DPI = metric.densityDpi;
+        WIDTH = metric.widthPixels;
+        HEIGHT = metric.heightPixels;
+    }
+}

+ 28 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/Jump2View.java

@@ -0,0 +1,28 @@
+package com.kfzs.cfyl.media.util;
+
+import android.app.Activity;
+import android.content.Intent;
+
+import com.kfzs.cfyl.media.activity.ActEditVideo;
+import com.sheep.gamegroup.model.entity.Video;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class Jump2View {
+    private static Jump2View jump2View;
+    public static Jump2View getInstance() {
+        if(jump2View == null)
+            jump2View = new Jump2View();
+        return jump2View;
+    }
+    private Jump2View(){
+
+    }
+    public void goActEditVideo(Activity activity, Video video){
+        Intent intent = new Intent(activity, ActEditVideo.class);
+        intent.putExtra(Video.class.getSimpleName(), video);
+        activity.startActivity(intent);
+    }
+}

+ 25 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/KeyEventUtil.java

@@ -0,0 +1,25 @@
+package com.kfzs.cfyl.media.util;
+
+import android.app.Instrumentation;
+
+/**
+ * Created by realicing on 2018/11/8.
+ * realicing@sina.com
+ */
+public class KeyEventUtil {
+    public static void sendKeyDownUp(final int keyCode) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    // 创建一个Instrumentation对象
+                    Instrumentation inst = new Instrumentation();
+                    // 调用inst对象的按键模拟方法
+                    inst.sendKeyDownUpSync(keyCode);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }).start();
+    }
+}

+ 44 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/LayoutParamsUtil.java

@@ -0,0 +1,44 @@
+package com.kfzs.cfyl.media.util;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+import com.kfzs.cfyl.media.bean.Lp;
+
+
+/**
+ * Created by realicing on 2018/11/13.
+ * realicing@sina.com
+ */
+public class LayoutParamsUtil {
+
+    //重新设置margin和宽高
+    public static void resetLayoutParams(View view, Lp lp) {
+        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
+        if (lp.getHeight() != Lp.NONE)
+            layoutParams.height = lp.getHeight();
+        if (lp.getWidth() != Lp.NONE)
+            layoutParams.width = lp.getWidth();
+        if (layoutParams instanceof RelativeLayout.LayoutParams) {
+            if (lp.getTopMargin() != Lp.NONE)
+                ((RelativeLayout.LayoutParams) layoutParams).topMargin = lp.getTopMargin();
+            if (lp.getLeftMargin() != Lp.NONE)
+                ((RelativeLayout.LayoutParams) layoutParams).leftMargin = lp.getLeftMargin();
+            if (lp.getBottomMargin() != Lp.NONE)
+                ((RelativeLayout.LayoutParams) layoutParams).bottomMargin = lp.getBottomMargin();
+            if (lp.getRightMargin() != Lp.NONE)
+                ((RelativeLayout.LayoutParams) layoutParams).rightMargin = lp.getRightMargin();
+        } else if (layoutParams instanceof LinearLayout.LayoutParams) {
+            if (lp.getTopMargin() != Lp.NONE)
+                ((LinearLayout.LayoutParams) layoutParams).topMargin = lp.getTopMargin();
+            if (lp.getLeftMargin() != Lp.NONE)
+                ((LinearLayout.LayoutParams) layoutParams).leftMargin = lp.getLeftMargin();
+            if (lp.getBottomMargin() != Lp.NONE)
+                ((LinearLayout.LayoutParams) layoutParams).bottomMargin = lp.getBottomMargin();
+            if (lp.getRightMargin() != Lp.NONE)
+                ((LinearLayout.LayoutParams) layoutParams).rightMargin = lp.getRightMargin();
+        }
+    }
+}

+ 228 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/ListUtil.java

@@ -0,0 +1,228 @@
+package com.kfzs.cfyl.media.util;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import rx.functions.Action1;
+
+/**
+ * Created by realicing on 2018/5/3.
+ * realicing@sina.com
+ */
+public class ListUtil {
+    public static <T> boolean hasIndex(List<T> list, int index) {
+        return !ListUtil.isEmpty(list) && list.size() > index && index > -1;
+    }
+
+    public static <T> boolean isEmpty(List<T> list) {
+        return list == null || list.isEmpty();
+    }
+
+    public static <T> void forEach(List<T> list, Action1<T> action1) {
+        if (list != null)
+            for (T t : list) {
+                action1.call(t);
+            }
+    }
+
+    public static <T> T getItem(List<T> list, int index) {
+        return hasIndex(list, index) ? list.get(index) : null;
+    }
+
+    public static <T> T getLast(List<T> list) {
+        int size = ListUtil.size(list);
+        return size > 0 ? list.get(-1 + size) : null;
+    }
+
+
+    public static int getTotalPage(int count, int per_page) {
+        return (count - 1) / per_page + 1;
+    }
+
+    public static <T> ArrayList<T> emptyList() {
+        return new ArrayList<>();
+    }
+
+
+    public static <T> int addAll(List<T> list, T... elements) {
+        return addAll(list, asList(elements));
+    }
+
+    public static <T> int addAll(List<T> list, List<? extends T> elements) {
+        int count = 0;
+        if (list == null) {
+            list = emptyList();
+        }
+        if (elements != null) {
+            for (T element : elements) {
+                int index = list.indexOf(element);
+                if (index != -1) {
+                    list.set(index, element);
+                } else if (list.add(element)) {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    public static <T> int addAll(List<T> list, List<? extends T> elements, int maxCount) {
+        int count = 0;
+        if (list == null) {
+            list = emptyList();
+        }
+        if (elements != null) {
+            for (T element : elements) {
+                int index = list.indexOf(element);
+                if (index != -1) {
+                    list.set(index, element);
+                } else if (list.add(element)) {
+                    count++;
+                }
+                if (count >= maxCount)//最多只加maxCount条数据
+                    break;
+            }
+        }
+        return count;
+    }
+
+    public static <T> int addAllItem(List<T> list, List<? extends T> elements) {
+        int count = 0;
+        if (list == null) {
+            list = emptyList();
+        }
+        if (elements != null) {
+            for (T element : elements) {
+                list.add(element);
+                count++;
+            }
+        }
+        return count;
+    }
+
+    public static <T> int addAllItem(List<T> list, List<? extends T> elements, int maxCount) {
+        int count = 0;
+        if (list == null) {
+            list = emptyList();
+        }
+        if (elements != null) {
+            for (T element : elements) {
+                list.add(element);
+                count++;
+                if (count >= maxCount)//最多只加maxCount条数据
+                    break;
+            }
+        }
+        return count;
+    }
+
+    public static <T> boolean isLastPosition(List<T> list, int position) {
+        return size(list) == position + 1;
+    }
+
+    public static <T> int size(List<T> list) {
+        return isEmpty(list) ? 0 : list.size();
+    }
+
+    @SafeVarargs
+    public static <T> ArrayList<T> asList(T... items) {
+        ArrayList<T> list = emptyList();
+        Collections.addAll(list, items);
+        return list;
+    }
+
+    public static <T> ArrayList<T> asList(List<T> itemList) {
+        if (itemList instanceof ArrayList) {
+            return (ArrayList<T>) itemList;
+        }
+        ArrayList<T> list = emptyList();
+        addAllItem(list, itemList);
+        return list;
+    }
+
+    @SafeVarargs
+    public static <T, R> ArrayList<R> asList(CallBack<T, R> callBack, T... items) {
+        ArrayList<R> list = emptyList();
+        for (T t : items) {
+            R r = callBack.call(t);
+            list.add(r);
+        }
+        return list;
+    }
+
+    public static <T, R> ArrayList<R> asList(CallBack<T, R> callBack, List<T> itemList, CallBack<T, Boolean> filterCallBack) {
+        ArrayList<R> list = emptyList();
+        for (T t : itemList) {
+            R r = callBack.call(t);
+            if (filterCallBack == null || filterCallBack.call(t))
+                list.add(r);
+        }
+        return list;
+    }
+
+    public static <T> ArrayList<T> removeItem(List<T> list, CallBack<T, Boolean> callBack) {
+        if (isEmpty(list)) {
+            return null;
+        }
+        ArrayList<T> removeList = emptyList();
+        for (T t : list) {
+            if (callBack.call(t))
+                removeList.add(t);
+        }
+        list.removeAll(removeList);
+        return removeList;
+    }
+
+    public static <T> T getItem(List<T> list, CallBack<T, Boolean> callBack) {
+        if (isEmpty(list)) {
+            return null;
+        }
+        for (T t : list) {
+            if (callBack.call(t))
+                return t;
+        }
+        return null;
+    }
+
+    public static <T> void set(List<T> list, T t, int position) {
+        if (hasIndex(list, position))
+            list.set(position, t);
+    }
+
+    /**
+     * 清除末尾的空数据
+     *
+     * @param list
+     */
+    public static <T> void removeNull(List<T> list) {
+        removeItem(list, new CallBack<T, Boolean>() {
+            @Override
+            public Boolean call(T t) {
+                return t == null || t.toString().isEmpty();
+            }
+        });
+    }
+
+    public static <T> void removeAll(List<T> allList, List<T> removeList) {
+        if (allList != null && removeList != null)
+            allList.removeAll(removeList);
+    }
+
+    //I 传入的数据, R 返回的结果
+    public static interface CallBack<I, R> {
+        public R call(I i);
+    }
+
+    //列表拼接为字符串
+    public static String listToUrls(List<String> list) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < list.size(); i++) {
+            if (i != 0)
+                sb.append(";");
+            sb.append(list.get(i));
+        }
+        return sb.toString();
+    }
+}

+ 324 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/VideoUtil.java

@@ -0,0 +1,324 @@
+package com.kfzs.cfyl.media.util;
+
+import android.graphics.Bitmap;
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.util.Log;
+
+import com.kfzs.cfyl.media.bean.VideoFrame;
+import com.kfzs.cfyl.share_library.util.LogUtil;
+import com.sheep.gamegroup.model.entity.Video;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import rx.functions.Action1;
+import wseemann.media.FFmpegMediaMetadataRetriever;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class VideoUtil {
+
+    public static Bitmap getVideoFrameBitmap(VideoFrame videoFrame) {
+        long time = System.currentTimeMillis();
+        long durationTime = time;
+        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
+        try {
+            mmr.setDataSource(videoFrame.getVideoPath());
+            durationTime = System.currentTimeMillis();
+            return mmr.getScaledFrameAtTime(videoFrame.getAtTime(), FFmpegMediaMetadataRetriever.OPTION_CLOSEST, videoFrame.getWidth(), videoFrame.getHeight());
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
+        } finally {
+            mmr.release();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功");
+        }
+        return null;
+    }
+    public static Bitmap getVideoFrameBitmap(Video video, long atTime, int width, int height) {
+        long time = System.currentTimeMillis();
+        long durationTime = time;
+        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
+        try {
+            mmr.setDataSource(video.getFilePath());
+            durationTime = System.currentTimeMillis();
+            Bitmap bitmap = mmr.getScaledFrameAtTime(atTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST, width, height);
+            return bitmap;
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
+        } finally {
+            mmr.release();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功");
+        }
+        return null;
+    }
+    public static ArrayList<Bitmap> getVideoFrameBitmapList(Video video, int size) {
+        ArrayList<Bitmap> arrayList = new ArrayList<>();
+        long time = System.currentTimeMillis();
+        long durationTime = time;
+        FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();
+        long duration = video.getDuration();
+        long per = duration * 1000L / size;
+        int max = 20;
+        int width = max, height = max;
+        if(video.getWidth() > video.getHeight()){
+            width = max * video.getWidth() / video.getHeight();
+        } else {
+            height = max * video.getHeight() / video.getWidth();
+        }
+        try {
+            mmr.setDataSource(video.getFilePath());
+            durationTime = System.currentTimeMillis();
+            for (int i = 0; i < size; i++) {
+                //这里单位为微秒
+                long atTime = i * per;
+                Bitmap bitmap = mmr.getScaledFrameAtTime(atTime, FFmpegMediaMetadataRetriever.OPTION_CLOSEST, width, height);
+                arrayList.add(bitmap);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t"+ (durationTime - time) + "\t" + e.getMessage());
+        } finally {
+            mmr.release();
+            Log.i("videoUtil", (System.currentTimeMillis() - time) + "\t" + (durationTime - time) + "\t 成功 "+ arrayList.size());
+        }
+        return arrayList;
+    }
+
+    public static void tryCutVideo(final String filePath, final long clipPoint, final long clipDuration, final Action1<Object> action1) {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                long time = System.currentTimeMillis();
+                Video video = cutVideo(filePath, clipPoint, clipDuration);
+                if (video == null) {
+                    action1.call(new Throwable("剪切失败"));
+                } else {
+                    action1.call(video);
+                }
+                long curTime = System.currentTimeMillis();
+                LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000);
+            }
+        }).start();
+    }
+
+    private static final String TAG = VideoUtil.class.getSimpleName();
+    /**
+     * 剪切视频
+     *
+     * @param url          源文本地址
+     * @param clipPoint    开始位置
+     * @param clipDuration 要剪切的长度
+     * @return 返回剪切出来的文件的地址
+     */
+    public static Video cutVideo(String url, long clipPoint, long clipDuration) {
+        Video video = new Video();
+        if (clipPoint < 0) {
+            Log.e(TAG, "clipPoint is error! but reset clipPoint " + clipPoint + "0 ");
+            clipPoint = 0;
+        }
+        LogUtil.println(TAG, url, clipPoint, clipDuration);
+        String outFilePath = getCutVideoFilePath(url, clipPoint, clipDuration);
+        video.setFilePath(outFilePath);
+        int videoTrackIndex = -1;
+        int audioTrackIndex = -1;
+        int videoMaxInputSize = 0;
+        int audioMaxInputSize = 0;
+        int sourceVTrack = 0;
+        int sourceATrack = 0;
+        long videoDuration, audioDuration;
+        //创建分离器
+        MediaExtractor mediaExtractor = new MediaExtractor();
+        MediaMuxer mediaMuxer = null;
+        MediaFormat mediaFormat;
+
+        try {
+            //设置文件路径
+            mediaExtractor.setDataSource(url);
+            //创建合成器
+            mediaMuxer = new MediaMuxer(outFilePath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+            String mime;
+            //获取每个轨道的信息
+            for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
+                mediaFormat = mediaExtractor.getTrackFormat(i);
+                mime = mediaFormat.getString(MediaFormat.KEY_MIME);
+                if (mime.startsWith("video/")) {
+                    sourceVTrack = i;
+                    int width = mediaFormat.getInteger(MediaFormat.KEY_WIDTH);
+                    int height = mediaFormat.getInteger(MediaFormat.KEY_HEIGHT);
+                    videoMaxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+                    videoDuration = mediaFormat.getLong(MediaFormat.KEY_DURATION);
+                    //检测剪辑点和剪辑时长是否正确
+                    if (clipPoint >= videoDuration) {
+                        Log.e(TAG, "clip point is error! but reset clipPoint " + clipPoint + " 0 ");
+                        clipPoint = 0;
+                    }
+                    if ((clipDuration + clipPoint) > videoDuration) {
+                        if (clipPoint == 0) {
+                            Log.e(TAG, "clip duration is error!"
+                                    + ";duration is " + videoDuration
+                                    + ";clipPoint is " + clipPoint
+                                    + ";clipDuration is " + clipDuration
+                                    + ";totalDuration is " + (clipDuration + clipPoint)
+                            );
+                            return null;
+                        }
+                        Log.e(TAG, "clip duration is error! but reset clipDuration " + clipDuration + "  " + (videoDuration - clipPoint));
+                        clipDuration = videoDuration - clipPoint;
+                    }
+                    Log.d(TAG, "width and height is " + width + " " + height
+                            + ";maxInputSize is " + videoMaxInputSize
+                            + ";duration is " + videoDuration
+                            + ";clipPoint is " + clipPoint
+                            + ";clipDuration is " + clipDuration
+                            + ";totalDuration is " + (clipDuration + clipPoint)
+                    );
+                    video.setWidth(width);
+                    video.setHeight(height);
+                    video.setDuration(clipDuration / 1000);//微秒转换为毫秒
+                    //向合成器添加视频轨
+                    videoTrackIndex = mediaMuxer.addTrack(mediaFormat);
+                } else if (mime.startsWith("audio/")) {
+                    sourceATrack = i;
+                    int sampleRate = mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+                    int channelCount = mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+                    audioMaxInputSize = mediaFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+                    audioDuration = mediaFormat.getLong(MediaFormat.KEY_DURATION);
+                    Log.d(TAG, "sampleRate is " + sampleRate
+                            + ";channelCount is " + channelCount
+                            + ";audioMaxInputSize is " + audioMaxInputSize
+                            + ";audioDuration is " + audioDuration
+                    );
+                    //添加音轨
+                    audioTrackIndex = mediaMuxer.addTrack(mediaFormat);
+                }
+                Log.d(TAG, "file mime is " + mime);
+            }
+            //分配缓冲
+            ByteBuffer inputBuffer = ByteBuffer.allocate(videoMaxInputSize);
+            //根据官方文档的解释MediaMuxer的start一定要在addTrack之后
+            mediaMuxer.start();
+            //视频处理部分
+            mediaExtractor.selectTrack(sourceVTrack);
+            MediaCodec.BufferInfo videoInfo = new MediaCodec.BufferInfo();
+            videoInfo.presentationTimeUs = 0;
+            long videoSampleTime;
+            //获取源视频相邻帧之间的时间间隔。(1)
+            {
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                //skip first I frame
+                if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC)
+                    mediaExtractor.advance();
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                long firstVideoPTS = mediaExtractor.getSampleTime();
+                mediaExtractor.advance();
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                long SecondVideoPTS = mediaExtractor.getSampleTime();
+                videoSampleTime = Math.abs(SecondVideoPTS - firstVideoPTS);
+                Log.d(TAG, "videoSampleTime is " + videoSampleTime);
+            }
+            //选择起点
+            mediaExtractor.seekTo(clipPoint, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
+            while (true) {
+                int sampleSize = mediaExtractor.readSampleData(inputBuffer, 0);
+                if (sampleSize < 0) {
+                    //这里一定要释放选择的轨道,不然另一个轨道就无法选中了
+                    mediaExtractor.unselectTrack(sourceVTrack);
+                    break;
+                }
+                int trackIndex = mediaExtractor.getSampleTrackIndex();
+                //获取时间戳
+                long presentationTimeUs = mediaExtractor.getSampleTime();
+                //获取帧类型,只能识别是否为I帧
+                int sampleFlag = mediaExtractor.getSampleFlags();
+                Log.d(TAG, "trackIndex is " + trackIndex
+                        + ";presentationTimeUs is " + presentationTimeUs
+                        + ";sampleFlag is " + sampleFlag
+                        + ";sampleSize is " + sampleSize);
+                //剪辑时间到了就跳出
+                if ((clipDuration != 0) && (presentationTimeUs > (clipPoint + clipDuration))) {
+                    mediaExtractor.unselectTrack(sourceVTrack);
+                    break;
+                }
+                mediaExtractor.advance();
+                videoInfo.offset = 0;
+                videoInfo.size = sampleSize;
+                videoInfo.flags = sampleFlag;
+                mediaMuxer.writeSampleData(videoTrackIndex, inputBuffer, videoInfo);
+                videoInfo.presentationTimeUs += videoSampleTime;//presentationTimeUs;
+            }
+            //音频部分
+            mediaExtractor.selectTrack(sourceATrack);
+            MediaCodec.BufferInfo audioInfo = new MediaCodec.BufferInfo();
+            audioInfo.presentationTimeUs = 0;
+            long audioSampleTime;
+            //获取音频帧时长
+            {
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                //skip first sample
+                if (mediaExtractor.getSampleTime() == 0)
+                    mediaExtractor.advance();
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                long firstAudioPTS = mediaExtractor.getSampleTime();
+                mediaExtractor.advance();
+                mediaExtractor.readSampleData(inputBuffer, 0);
+                long SecondAudioPTS = mediaExtractor.getSampleTime();
+                audioSampleTime = Math.abs(SecondAudioPTS - firstAudioPTS);
+                Log.d(TAG, "AudioSampleTime is " + audioSampleTime);
+            }
+            mediaExtractor.seekTo(clipPoint, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+            while (true) {
+                int sampleSize = mediaExtractor.readSampleData(inputBuffer, 0);
+                if (sampleSize < 0) {
+                    mediaExtractor.unselectTrack(sourceATrack);
+                    break;
+                }
+                int trackIndex = mediaExtractor.getSampleTrackIndex();
+                long presentationTimeUs = mediaExtractor.getSampleTime();
+                Log.d(TAG, "trackIndex is " + trackIndex
+                        + ";presentationTimeUs is " + presentationTimeUs);
+                if ((clipDuration != 0) && (presentationTimeUs > (clipPoint + clipDuration))) {
+                    mediaExtractor.unselectTrack(sourceATrack);
+                    break;
+                }
+                mediaExtractor.advance();
+                audioInfo.offset = 0;
+                audioInfo.size = sampleSize;
+                mediaMuxer.writeSampleData(audioTrackIndex, inputBuffer, audioInfo);
+                audioInfo.presentationTimeUs += audioSampleTime;//presentationTimeUs;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, " read error " + e.getMessage());
+        } finally {
+            //全部写完后释放MediaMuxer和MediaExtractor
+            if (mediaMuxer != null) {
+                mediaMuxer.stop();
+                mediaMuxer.release();
+            }
+            mediaExtractor.release();
+        }
+        return video;
+    }
+    /**
+     * 获取可以剪切出的视频的地址
+     *
+     * @param url          源文本地址
+     * @param clipPoint    开始位置
+     * @param clipDuration 要剪切的长度
+     * @return 返回可以剪切出来的文件的地址
+     */
+    public static String getCutVideoFilePath(String url, long clipPoint, long clipDuration) {
+        if (clipPoint < 0) {
+            Log.e(TAG, "clipPoint is error! but reset clipPoint " + clipPoint + "0 ");
+            clipPoint = 0;
+        }
+        return String.format(Locale.CHINA, "%s_%d_%d.%s", url.substring(0, url.lastIndexOf(".")), clipPoint, clipDuration, FileUtil.getExtensionName(url));
+    }
+}

+ 106 - 0
media/app/src/main/java/com/kfzs/cfyl/media/util/ViewUtil.java

@@ -0,0 +1,106 @@
+package com.kfzs.cfyl.media.util;
+
+import android.support.annotation.StringRes;
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+import com.kfzs.cfyl.media.R;
+import com.kfzs.cfyl.media.api.IFilter;
+import com.kfzs.cfyl.media.glide.FilterTransform;
+
+import java.util.Locale;
+
+/**
+ * Created by realicing on 2018/12/6.
+ * realicing@sina.com
+ */
+public class ViewUtil {
+    public static void setEnabled(View view, boolean enabled) {
+        if (view != null) {
+            view.setEnabled(enabled);
+        }
+    }
+
+    public static void setVisibility(View view, boolean isVisible) {
+        if (view != null) {
+            view.setVisibility(isVisible ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    public static void toggleVisibility(View view) {
+        if (view != null) {
+            view.setVisibility(isVisible(view) ? View.GONE : View.VISIBLE);
+        }
+    }
+
+    public static boolean isVisible(View view) {
+        return view != null && view.getVisibility() == View.VISIBLE;
+    }
+
+    public static void setVisibility2(View view, boolean isVisible) {
+        if (view != null) {
+            view.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
+        }
+    }
+    public static void setText(TextView textView) {
+        if (textView != null) {
+            textView.setText("");
+        }
+    }
+
+    public static void setText(TextView textView, CharSequence msg) {
+        if (textView != null) {
+            textView.setText(TextUtils.isEmpty(msg) ? "" : msg);
+        }
+    }
+
+    public static void setText(TextView textView, @StringRes int stringId, Object... objects) {
+        if (textView != null) {
+            textView.setText(textView.getContext().getString(stringId, objects));
+        }
+    }
+
+    public static void setText(TextView textView, String format, Object... objects) {
+        if (textView != null) {
+            textView.setText(String.format(Locale.CHINA, format, objects));
+        }
+    }
+    //加载默认原图滤镜效果
+    public static void setImage(ImageView imageView, final IFilter filter) {
+        if (imageView != null && filter != null && filter.getConfig() != null) {
+            String url = getNetImgByName("alter_original");
+            if(filter.getConfig().isEmpty()){
+                setImage(imageView, url);
+                return;
+            }
+            Glide.with(imageView.getContext())
+                    .load(url)
+                    .apply(new RequestOptions().transform(new FilterTransform(filter)))
+                    .into(imageView);
+        }
+    }
+    public static void setImage(ImageView imageView, String pictures) {
+        if (imageView != null) {
+            if (TextUtils.isEmpty(pictures)) {
+                imageView.setImageResource(R.drawable.sheep_logo);
+            } else {
+                if (pictures.contains(";")) {
+                    pictures = pictures.split(";")[0];
+                }
+                Glide.with(imageView.getContext())
+                        .load(pictures)
+                        .into(imageView);
+            }
+        }
+    }
+    public static String getNetImgByName(String name) {
+        return String.format(Locale.CHINA, "http://cdngame.kuaifazs.com/%s.png", name);
+    }
+    public static String getNetImgByNameAndSuffix(String name) {
+        return String.format(Locale.CHINA, "http://cdngame.kuaifazs.com/%s", name);
+    }
+}

+ 9 - 0
media/app/src/main/res/color/selector_color_white_40.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_activated="true" android:color="@color/white" />
+    <item android:state_focused="true" android:color="@color/white" />
+    <item android:state_checked="true" android:color="@color/white"/>
+    <item android:state_selected="true" android:color="@color/white"/>
+    <item android:state_pressed="true" android:color="@color/white"/>
+    <item android:color="@color/white_40"/>
+</selector>

File diff suppressed because it is too large
+ 34 - 0
media/app/src/main/res/drawable-v24/ic_launcher_foreground.xml


+ 9 - 0
media/app/src/main/res/drawable-v24/shape_black_solid_rectangle_top_6.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners
+        android:topLeftRadius="6dp"
+        android:topRightRadius="6dp" />
+    <solid android:color="#000000" />
+
+</shape>

BIN
media/app/src/main/res/drawable-xhdpi/narrow_back_white.webp


BIN
media/app/src/main/res/drawable-xxhdpi/narrow_back_black.webp


BIN
media/app/src/main/res/drawable-xxhdpi/qiandao.webp


BIN
media/app/src/main/res/drawable-xxhdpi/sheep_logo.png


BIN
media/app/src/main/res/drawable-xxhdpi/sheep_logo_3.png


+ 10 - 0
media/app/src/main/res/drawable/button_full_normal_gray.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="30dp" />
+
+    <stroke
+        android:width="1dp"
+        android:color="@color/gray_6" />
+    <solid android:color="@color/gray_6" />
+</shape>

+ 9 - 0
media/app/src/main/res/drawable/button_full_normal_main_click.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="30dp" />
+
+    <gradient
+        android:startColor="@color/theme_app_highlight_transparent"
+        android:endColor="@color/theme_app_highlight_more_transparent"/>
+</shape>

+ 170 - 0
media/app/src/main/res/drawable/ic_launcher_background.xml

@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>

+ 9 - 0
media/app/src/main/res/drawable/selector_button_full_main.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+  <item android:state_enabled="false" android:drawable="@drawable/button_full_normal_gray" />
+  <item android:state_focused="true" android:drawable="@drawable/button_full_normal_main_click" />
+  <item android:state_checked="true" android:drawable="@drawable/button_full_normal_main_click"/>
+  <item android:state_selected="true" android:drawable="@drawable/button_full_normal_main_click"/>
+  <item android:state_pressed="true" android:drawable="@drawable/button_full_normal_main_click"/>
+  <item android:drawable="@drawable/sp_bg_gradient_rectangle_blue"/>
+</selector>

+ 5 - 0
media/app/src/main/res/drawable/shape_oval_main.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="@color/btn_color_main_stroke" />
+</shape>

+ 6 - 0
media/app/src/main/res/drawable/shape_white_20_solid_rectangle_15.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="15dp" />
+    <solid android:color="#33ffffff" />
+</shape>

+ 6 - 0
media/app/src/main/res/drawable/shape_white_solid_rectangle_5.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="5dp" />
+    <solid android:color="#ffffff" />
+</shape>

+ 12 - 0
media/app/src/main/res/drawable/sp_bg_gradient_rectangle_blue.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <gradient
+        android:startColor="@color/blue_start"
+        android:endColor="@color/blue_end"/>
+
+    <corners
+        android:radius="25dp"/>
+
+</shape>

+ 2 - 2
app/src/main/res/layout/act_cut_video.xml

@@ -5,7 +5,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="#000000"
-    tools:context="com.sheep.gamegroup.view.activity.ActCutVideo">
+    tools:context=".activity.ActCutVideo">
 
     <VideoView
         android:id="@+id/videoView"
@@ -86,7 +86,7 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintTop_toBottomOf="@id/edit_video_topic_tv" />
 
-    <com.sheep.gamegroup.view.customview.VideoFramesView
+    <com.kfzs.cfyl.media.customview.VideoFramesView
         android:id="@+id/videoFramesView"
         android:layout_width="match_parent"
         android:layout_height="69dp"

+ 86 - 0
media/app/src/main/res/layout/act_edit_video.xml

@@ -0,0 +1,86 @@
+<?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"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context=".activity.ActEditVideo">
+
+    <FrameLayout
+        android:id="@+id/glviewFrameLayout"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <org.wysaid.view.VideoPlayerGLSurfaceView
+            android:id="@+id/videoGLSurfaceView"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+    </FrameLayout>
+
+    <HorizontalScrollView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:visibility="gone">
+
+        <LinearLayout
+            android:id="@+id/menuLinearLayout"
+            android:layout_width="wrap_content"
+            android:layout_height="50dp"
+            android:visibility="gone">
+
+            <Button
+                android:id="@+id/galleryBtn"
+                android:layout_width="100dp"
+                android:layout_height="50dp"
+                android:text="Gallery" />
+
+            <Button
+                android:id="@+id/takeShotBtn"
+                android:layout_width="100dp"
+                android:layout_height="match_parent"
+                android:text="TakeShot" />
+
+            <Button
+                android:id="@+id/switchShapeBtn"
+                android:layout_width="100dp"
+                android:layout_height="match_parent"
+                android:text="Border" />
+
+            <Button
+                android:id="@+id/fitViewBtn"
+                android:layout_width="100dp"
+                android:layout_height="match_parent"
+                android:text="FitScreen" />
+
+        </LinearLayout>
+    </HorizontalScrollView>
+
+    <FrameLayout
+        android:id="@+id/frame_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true" />
+
+
+    <LinearLayout
+        android:id="@+id/seekBarLl"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_marginBottom="40dp"
+        android:orientation="vertical"
+        android:visibility="gone" />
+
+    <ImageView
+        android:id="@+id/act_edit_video_commit_iv"
+        android:layout_width="30dp"
+        android:layout_height="30dp"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentEnd="true"
+        android:onClick="onClickCommit"
+        android:layout_marginTop="27dp"
+        android:layout_marginEnd="16dp"
+        android:background="@drawable/shape_oval_main"
+        android:padding="5dp"
+        android:src="@drawable/qiandao" />
+</RelativeLayout>

+ 5 - 0
media/app/src/main/res/layout/common_container.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />

+ 6 - 0
media/app/src/main/res/layout/common_rv.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/recyclerView"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:descendantFocusability="blocksDescendants" />

app/src/main/res/layout/custom_video_frames_view.xml → media/app/src/main/res/layout/custom_video_frames_view.xml


+ 0 - 0
media/app/src/main/res/layout/dialog_loading.xml


Some files were not shown because too many files changed in this diff