Explorar el Código

Merge branch 'sheep_develop' of 10.8.230.114:xmy_android/small_sheep_android into sheep_develop

hanjing hace 7 años
padre
commit
9451b29568
Se han modificado 73 ficheros con 4969 adiciones y 163 borrados
  1. 0 1
      .idea/gradle.xml
  2. 1 1
      RxGalleryFinal/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java
  3. 4 3
      app/build.gradle
  4. 12 2
      app/src/main/AndroidManifest.xml
  5. 14 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/api/CameraCallBack.java
  6. 69 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java
  7. 283 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java
  8. 1060 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java
  9. 506 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java
  10. 170 0
      app/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java
  11. 9 0
      app/src/main/java/com/kfzs/duanduan/utils/NumberFormatUtils.java
  12. 7 4
      app/src/main/java/com/kfzs/duanduan/view/DialogStorageLow.java
  13. 75 0
      app/src/main/java/com/sheep/gamegroup/absBase/AbsApiRefresh.java
  14. 4 1
      app/src/main/java/com/sheep/gamegroup/absBase/AbsObserver.java
  15. 9 0
      app/src/main/java/com/sheep/gamegroup/absBase/BaseActivity.java
  16. 48 0
      app/src/main/java/com/sheep/gamegroup/absBase/CheckErrorApiRefresh.java
  17. 19 0
      app/src/main/java/com/sheep/gamegroup/absBase/IApiRefresh.java
  18. 22 9
      app/src/main/java/com/sheep/gamegroup/absBase/ApiRefresh.java
  19. 119 0
      app/src/main/java/com/sheep/gamegroup/find/activity/ActMediaChoose.java
  20. 109 0
      app/src/main/java/com/sheep/gamegroup/find/fragment/FgtMediaPickerImg.java
  21. 126 0
      app/src/main/java/com/sheep/gamegroup/find/fragment/FgtMediaPickerVideo.java
  22. 15 0
      app/src/main/java/com/sheep/gamegroup/greendao/DDProviderHelper.java
  23. 2 2
      app/src/main/java/com/sheep/gamegroup/greendao/download/DaoMaster.java
  24. 16 2
      app/src/main/java/com/sheep/gamegroup/greendao/download/DownLoadInfo.java
  25. 16 2
      app/src/main/java/com/sheep/gamegroup/greendao/download/DownLoadInfoDao.java
  26. 1 1
      app/src/main/java/com/sheep/gamegroup/model/api/ApiService.java
  27. 3 3
      app/src/main/java/com/sheep/gamegroup/model/entity/DiscoveryVideo.java
  28. 36 0
      app/src/main/java/com/sheep/gamegroup/model/entity/Lp.java
  29. 70 0
      app/src/main/java/com/sheep/gamegroup/model/entity/Video.java
  30. 25 4
      app/src/main/java/com/sheep/gamegroup/util/FileUtil.java
  31. 35 1
      app/src/main/java/com/sheep/gamegroup/util/Jump2View.java
  32. 359 0
      app/src/main/java/com/sheep/gamegroup/util/MediaHandleUtil.java
  33. 226 0
      app/src/main/java/com/sheep/gamegroup/util/MediaMetadataRetrieverUtil.java
  34. 1 1
      app/src/main/java/com/sheep/gamegroup/util/TestUtil.java
  35. 1 1
      app/src/main/java/com/sheep/gamegroup/util/TimeUtil.java
  36. 60 12
      app/src/main/java/com/sheep/gamegroup/util/ViewUtil.java
  37. 510 0
      app/src/main/java/com/sheep/gamegroup/view/activity/ActCutVideo.java
  38. 38 0
      app/src/main/java/com/sheep/gamegroup/view/activity/ActEditVideo.java
  39. 1 1
      app/src/main/java/com/sheep/gamegroup/view/activity/ActMain.java
  40. 2 1
      app/src/main/java/com/sheep/gamegroup/view/activity/ActPlayVideo.java
  41. 7 1
      app/src/main/java/com/sheep/gamegroup/view/activity/ActPlayVideoArticle.java
  42. 45 44
      app/src/main/java/com/sheep/gamegroup/view/activity/ActPublishArticle.java
  43. 7 1
      app/src/main/java/com/sheep/gamegroup/view/adapter/AdpVideo.java
  44. 268 0
      app/src/main/java/com/sheep/gamegroup/view/customview/VideoFramesView.java
  45. 8 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment.java
  46. 18 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment2.java
  47. 8 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment3.java
  48. 8 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment4.java
  49. 8 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment5.java
  50. 41 39
      app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment6.java
  51. 0 1
      app/src/main/java/com/sheep/gamegroup/view/fragment/FgtArticleVideo.java
  52. 83 0
      app/src/main/java/com/sheep/gamegroup/view/fragment/FgtDiscoveryTopic.java
  53. 6 6
      app/src/main/java/com/sheep/gamegroup/view/fragment/FgtUserFocusLogList.java
  54. 34 0
      app/src/main/java/com/sheep/jiuyan/samllsheep/base/BaseFragment.java
  55. 23 4
      app/src/main/java/com/sheep/jiuyan/samllsheep/service/DownloadService.java
  56. 1 1
      app/src/main/java/com/sheep/jiuyan/samllsheep/utils/G.java
  57. 6 0
      app/src/main/res/drawable/shape_oval_solid_10_f5.xml
  58. 6 0
      app/src/main/res/drawable/shape_oval_solid_10_main.xml
  59. 6 0
      app/src/main/res/drawable/shape_white_20_solid_rectangle_15.xml
  60. 10 0
      app/src/main/res/layout/act_cut_video.xml
  61. 109 0
      app/src/main/res/layout/act_edit_video.xml
  62. 22 0
      app/src/main/res/layout/act_media_choose.xml
  63. 59 0
      app/src/main/res/layout/custom_video_frames_view.xml
  64. 34 0
      app/src/main/res/layout/include_lll.xml
  65. 20 0
      app/src/main/res/layout/item_discovery_topic.xml
  66. 6 0
      app/src/main/res/layout/item_iv_mh.xml
  67. 29 0
      app/src/main/res/layout/item_media_picker.xml
  68. 4 4
      app/src/main/res/layout/line_1px_hor.xml
  69. BIN
      app/src/main/res/mipmap-xxhdpi/ic_open_camera.webp
  70. 1 0
      app/src/main/res/values/colors.xml
  71. 2 0
      app/src/main/res/values/strings.xml
  72. 1 1
      settings.gradle
  73. 6 4
      view/src/main/java/com/kfzs/android/view/widget/WrapContentHeightViewPager.java

+ 0 - 1
.idea/gradle.xml

@@ -8,7 +8,6 @@
         <option name="modules">
         <option name="modules">
           <set>
           <set>
             <option value="$PROJECT_DIR$" />
             <option value="$PROJECT_DIR$" />
-            <option value="$PROJECT_DIR$/RxGalleryFinal" />
             <option value="$PROJECT_DIR$/WaterWaveProgress" />
             <option value="$PROJECT_DIR$/WaterWaveProgress" />
             <option value="$PROJECT_DIR$/app" />
             <option value="$PROJECT_DIR$/app" />
             <option value="$PROJECT_DIR$/ucrop" />
             <option value="$PROJECT_DIR$/ucrop" />

+ 1 - 1
RxGalleryFinal/src/main/java/cn/finalteam/rxgalleryfinal/ui/adapter/MediaGridAdapter.java

@@ -109,7 +109,7 @@ public class MediaGridAdapter extends RecyclerView.Adapter<MediaGridAdapter.Grid
                 holder.tv_media_duration.setVisibility(View.VISIBLE);
                 holder.tv_media_duration.setVisibility(View.VISIBLE);
                 long second = mediaBean.getDuration() / 1000;
                 long second = mediaBean.getDuration() / 1000;
                 long m = second / 60;
                 long m = second / 60;
-                holder.tv_media_duration.setText(String.format(Locale.CHINA, "%d:%d", m, second % 60));
+                holder.tv_media_duration.setText(String.format(Locale.CHINA, "%d:%02d", m, second % 60));
             } else {
             } else {
                 holder.tv_media_duration.setVisibility(View.GONE);
                 holder.tv_media_duration.setVisibility(View.GONE);
                 holder.mCbCheck.setVisibility(View.VISIBLE);
                 holder.mCbCheck.setVisibility(View.VISIBLE);

+ 4 - 3
app/build.gradle

@@ -23,7 +23,7 @@ android {
         flavorDimensions "versionCode"
         flavorDimensions "versionCode"
     }
     }
     greendao {
     greendao {
-        schemaVersion 14
+        schemaVersion 15
         targetGenDir 'src/main/java'
         targetGenDir 'src/main/java'
     }
     }
 //    compileOptions{
 //    compileOptions{
@@ -325,7 +325,7 @@ dependencies {
     //    implementation 'com.github.yalantis:ucrop:2.2.1-native'
     //    implementation 'com.github.yalantis:ucrop:2.2.1-native'
 
 
     //    implementation 'com.google.zxing:core:3.3.0'
     //    implementation 'com.google.zxing:core:3.3.0'
-//    implementation project(':ucrop')
+    implementation project(':ucrop')
     implementation ('com.sunfusheng:marqueeview:1.3.3') {
     implementation ('com.sunfusheng:marqueeview:1.3.3') {
         exclude group: 'com.android.support', module: 'appcompat-v7'
         exclude group: 'com.android.support', module: 'appcompat-v7'
     }
     }
@@ -385,7 +385,8 @@ dependencies {
 //        exclude group: 'com.android.support', module: 'recyclerview-v7'
 //        exclude group: 'com.android.support', module: 'recyclerview-v7'
 //    }
 //    }
 //    implementation "com.android.support:exifinterface:$supportLibVersion"
 //    implementation "com.android.support:exifinterface:$supportLibVersion"
-    implementation project(':RxGalleryFinal')
+//    implementation project(':RxGalleryFinal')
+    implementation "com.android.support:exifinterface:$supportLibVersion"
     implementation ('com.qiniu:qiniu-android-sdk:7.3.13') {
     implementation ('com.qiniu:qiniu-android-sdk:7.3.13') {
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
         exclude group: 'com.squareup.okhttp3', module: 'okhttp'
     }
     }

+ 12 - 2
app/src/main/AndroidManifest.xml

@@ -448,6 +448,16 @@
             android:screenOrientation="user"
             android:screenOrientation="user"
             android:theme="@style/AppTheme.noTitleBar" />
             android:theme="@style/AppTheme.noTitleBar" />
         <activity
         <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.view.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:name="com.sheep.gamegroup.view.activity.ActInputAndPickerImg"
             android:theme="@style/AppTheme.translucent" />
             android:theme="@style/AppTheme.translucent" />
         <activity
         <activity
@@ -882,8 +892,8 @@
 
 
         <!-- 小绵羊3.4.5 选择图片与视频  -->
         <!-- 小绵羊3.4.5 选择图片与视频  -->
         <activity
         <activity
-            android:name="cn.finalteam.rxgalleryfinal.ui.activity.MediaActivity"
-            android:exported="true" />
+            android:name="com.sheep.gamegroup.find.activity.ActMediaChoose"
+            android:screenOrientation="portrait" />
     </application>
     </application>
 
 
 </manifest>
 </manifest>

+ 14 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/api/CameraCallBack.java

@@ -0,0 +1,14 @@
+package cn.finalteam.rxgalleryfinal.api;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ */
+public interface CameraCallBack {
+
+    void onGetImageSuccess(String cropFilePath);
+
+    void onGetVideoSuccess();
+
+    void onCropImageSuccess();
+}

+ 69 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/bean/BucketBean.java

@@ -0,0 +1,69 @@
+package cn.finalteam.rxgalleryfinal.bean;
+
+import android.text.TextUtils;
+
+/**
+ * Desction:文件夹信息
+ * Author:pengjianbo  Dujinyang
+ * Date:16/6/9 下午2:47
+ */
+public class BucketBean {
+    private String bucketId;
+    private String bucketName;
+    private int imageCount;
+    private String cover;
+    //图片方向
+    private int orientation;
+
+    public String getBucketId() {
+        return bucketId;
+    }
+
+    public void setBucketId(String bucketId) {
+        this.bucketId = bucketId;
+    }
+
+    public String getBucketName() {
+        return bucketName;
+    }
+
+    public void setBucketName(String bucketName) {
+        this.bucketName = bucketName;
+    }
+
+    public int getImageCount() {
+        return imageCount;
+    }
+
+    public void setImageCount(int imageCount) {
+        this.imageCount = imageCount;
+    }
+
+    public String getCover() {
+        if (cover == null) {
+            return "";
+        }
+        return cover;
+    }
+
+    public void setCover(String cover) {
+        this.cover = cover;
+    }
+
+    public int getOrientation() {
+        return orientation;
+    }
+
+    public void setOrientation(int orientation) {
+        this.orientation = orientation;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof BucketBean)) {
+            return false;
+        }
+        BucketBean bucketBean = (BucketBean) o;
+        return TextUtils.equals(bucketBean.getBucketId(), getBucketId());
+    }
+}

+ 283 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/bean/MediaBean.java

@@ -0,0 +1,283 @@
+package cn.finalteam.rxgalleryfinal.bean;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.File;
+
+/**
+ * Desction:Media Bean
+ * Author:pengjianbo  Dujinyang
+ * Date:16/5/4 下午4:14
+ */
+public class MediaBean implements Parcelable {
+
+    public static final Creator<MediaBean> CREATOR = new Creator<MediaBean>() {
+        @Override
+        public MediaBean createFromParcel(Parcel in) {
+            return new MediaBean(in);
+        }
+
+        @Override
+        public MediaBean[] newArray(int size) {
+            return new MediaBean[size];
+        }
+    };
+    //图片ID
+    private long id;
+    private String title;
+    //图片、视频源地址
+    private String originalPath;
+    //图片、视频创建时间
+    private long createDate;
+    //图片、视频最后修改时间
+    private long modifiedDate;
+    //媒体类型
+    private String mimeType;
+    //宽
+    private int width;
+    //高
+    private int height;
+    //纬度
+    private double latitude;
+    //经度
+    private double longitude;
+    //图片方向
+    private int orientation;
+    //文件大小
+    private long length;
+    //时长
+    private long duration;
+    //文件夹相关
+    private String bucketId;
+    private String bucketDisplayName;
+    //大缩略图
+    private String thumbnailBigPath;
+    //小缩略图
+    private String thumbnailSmallPath;
+
+    public MediaBean() {
+    }
+
+    MediaBean(Parcel in) {
+        id = in.readLong();
+        title = in.readString();
+        originalPath = in.readString();
+        createDate = in.readLong();
+        modifiedDate = in.readLong();
+        mimeType = in.readString();
+        bucketId = in.readString();
+        bucketDisplayName = in.readString();
+        thumbnailBigPath = in.readString();
+        thumbnailSmallPath = in.readString();
+        width = in.readInt();
+        height = in.readInt();
+        latitude = in.readDouble();
+        longitude = in.readDouble();
+        orientation = in.readInt();
+        length = in.readLong();
+        duration = in.readLong();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(id);
+        dest.writeString(title);
+        dest.writeString(originalPath);
+        dest.writeLong(createDate);
+        dest.writeLong(modifiedDate);
+        dest.writeString(mimeType);
+        dest.writeString(bucketId);
+        dest.writeString(bucketDisplayName);
+        dest.writeString(thumbnailBigPath);
+        dest.writeString(thumbnailSmallPath);
+        dest.writeInt(width);
+        dest.writeInt(height);
+        dest.writeDouble(latitude);
+        dest.writeDouble(longitude);
+        dest.writeInt(orientation);
+        dest.writeLong(length);
+        dest.writeLong(duration);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getOriginalPath() {
+        return originalPath;
+    }
+
+    public void setOriginalPath(String originalPath) {
+        this.originalPath = originalPath;
+    }
+
+    public long getCreateDate() {
+        return createDate;
+    }
+
+    public void setCreateDate(long createDate) {
+        this.createDate = createDate;
+    }
+
+    public long getModifiedDate() {
+        return modifiedDate;
+    }
+
+    public void setModifiedDate(long modifiedDate) {
+        this.modifiedDate = modifiedDate;
+    }
+
+    public String getMimeType() {
+        return mimeType;
+    }
+
+    public void setMimeType(String mimeType) {
+        this.mimeType = mimeType;
+    }
+
+    public String getBucketId() {
+        return bucketId;
+    }
+
+    public void setBucketId(String bucketId) {
+        this.bucketId = bucketId;
+    }
+
+    public String getBucketDisplayName() {
+        return bucketDisplayName;
+    }
+
+    public void setBucketDisplayName(String bucketDisplayName) {
+        this.bucketDisplayName = bucketDisplayName;
+    }
+
+    public String getThumbnailBigPath() {
+        if (new File(thumbnailBigPath).exists()) {
+            return thumbnailBigPath;
+        }
+        return "";
+    }
+
+    public void setThumbnailBigPath(String thumbnailBigPath) {
+        this.thumbnailBigPath = thumbnailBigPath;
+    }
+
+    public String getThumbnailSmallPath() {
+        if (new File(thumbnailSmallPath).exists()) {
+            return thumbnailSmallPath;
+        }
+        return "";
+    }
+
+    public void setThumbnailSmallPath(String thumbnailSmallPath) {
+        this.thumbnailSmallPath = thumbnailSmallPath;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public double getLatitude() {
+        return latitude;
+    }
+
+    public void setLatitude(double latitude) {
+        this.latitude = latitude;
+    }
+
+    public double getLongitude() {
+        return longitude;
+    }
+
+    public void setLongitude(double longitude) {
+        this.longitude = longitude;
+    }
+
+    public int getOrientation() {
+        return orientation;
+    }
+
+    public void setOrientation(int orientation) {
+        this.orientation = orientation;
+    }
+
+    public long getLength() {
+        return length;
+    }
+
+    public void setLength(long length) {
+        this.length = length;
+    }
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || !(obj instanceof MediaBean)) {
+            return false;
+        }
+
+        MediaBean bean = (MediaBean) obj;
+        return bean.getId() == getId();
+
+    }
+
+    @Override
+    public String toString() {
+        return "MediaBean{" +
+                "id=" + id +
+                ", title='" + title + '\'' +
+                ", originalPath='" + originalPath + '\'' +
+                ", createDate=" + createDate +
+                ", modifiedDate=" + modifiedDate +
+                ", mimeType='" + mimeType + '\'' +
+                ", width=" + width +
+                ", height=" + height +
+                ", latitude=" + latitude +
+                ", longitude=" + longitude +
+                ", orientation=" + orientation +
+                ", length=" + length +
+                ", duration=" + duration +
+                ", bucketId='" + bucketId + '\'' +
+                ", bucketDisplayName='" + bucketDisplayName + '\'' +
+                ", thumbnailBigPath='" + thumbnailBigPath + '\'' +
+                ", thumbnailSmallPath='" + thumbnailSmallPath + '\'' +
+                '}';
+    }
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1060 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/utils/FilenameUtils.java


+ 506 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/utils/MediaUtils.java

@@ -0,0 +1,506 @@
+package cn.finalteam.rxgalleryfinal.utils;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.MediaStore;
+import android.support.annotation.Nullable;
+import android.support.media.ExifInterface;
+import android.text.TextUtils;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.ClassFileHelper;
+import com.yalantis.ucrop.UCrop;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import cn.finalteam.rxgalleryfinal.api.CameraCallBack;
+import cn.finalteam.rxgalleryfinal.bean.BucketBean;
+import cn.finalteam.rxgalleryfinal.bean.MediaBean;
+
+/**
+ * Desction:媒体获取工具
+ * Author:pengjianbo  Dujinyang
+ * Date:16/5/4 下午4:11
+ */
+public class MediaUtils {
+
+    public static List<MediaBean> getMediaWithImageList(Context context, int page, int limit) {
+        return getMediaWithImageList(context, String.valueOf(Integer.MIN_VALUE), page, limit);
+    }
+
+    /**
+     * 从数据库中读取图片
+     */
+    public static List<MediaBean> getMediaWithImageList(Context context, String bucketId, int page, int limit) {
+        int offset = (page - 1) * limit;
+        List<MediaBean> mediaBeanList = new ArrayList<>();
+        ContentResolver contentResolver = context.getContentResolver();
+        List<String> projection = new ArrayList<>();
+        projection.add(MediaStore.Images.Media._ID);
+        projection.add(MediaStore.Images.Media.TITLE);
+        projection.add(MediaStore.Images.Media.DATA);
+        projection.add(MediaStore.Images.Media.BUCKET_ID);
+        projection.add(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
+        projection.add(MediaStore.Images.Media.MIME_TYPE);
+        projection.add(MediaStore.Images.Media.DATE_ADDED);
+        projection.add(MediaStore.Images.Media.DATE_MODIFIED);
+        projection.add(MediaStore.Images.Media.LATITUDE);
+        projection.add(MediaStore.Images.Media.LONGITUDE);
+        projection.add(MediaStore.Images.Media.ORIENTATION);
+        projection.add(MediaStore.Images.Media.SIZE);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            projection.add(MediaStore.Images.Media.WIDTH);
+            projection.add(MediaStore.Images.Media.HEIGHT);
+        }
+        String selection = null;
+        String[] selectionArgs = null;
+        if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
+            selection = MediaStore.Images.Media.BUCKET_ID + "=?";
+            selectionArgs = new String[]{bucketId};
+        }
+        Cursor cursor = contentResolver.query(
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection,
+                selectionArgs, MediaStore.Images.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset);
+        if (cursor != null) {
+            int count = cursor.getCount();
+            if (count > 0) {
+                cursor.moveToFirst();
+                do {
+                    MediaBean mediaBean = parseImageCursorAndCreateThumImage(context, cursor);
+                    mediaBeanList.add(mediaBean);
+                } while (cursor.moveToNext());
+            }
+        }
+
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
+        }
+        return mediaBeanList;
+    }
+
+    public static List<MediaBean> getMediaWithVideoList(Context context, int page, int limit) {
+        return getMediaWithVideoList(context, String.valueOf(Integer.MIN_VALUE), page, limit);
+    }
+
+    /**
+     * 从数据库中读取视频
+     */
+    public static List<MediaBean> getMediaWithVideoList(Context context, String bucketId, int page, int limit) {
+        int offset = (page - 1) * limit;
+        List<MediaBean> mediaBeanList = new ArrayList<>();
+        ContentResolver contentResolver = context.getContentResolver();
+        List<String> projection = new ArrayList<>();
+        projection.add(MediaStore.Video.Media._ID);
+        projection.add(MediaStore.Video.Media.TITLE);
+        projection.add(MediaStore.Video.Media.DATA);
+        projection.add(MediaStore.Video.Media.BUCKET_ID);
+        projection.add(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
+        projection.add(MediaStore.Video.Media.MIME_TYPE);
+        projection.add(MediaStore.Video.Media.DATE_ADDED);
+        projection.add(MediaStore.Video.Media.DATE_MODIFIED);
+        projection.add(MediaStore.Video.Media.LATITUDE);
+        projection.add(MediaStore.Video.Media.LONGITUDE);
+        projection.add(MediaStore.Video.Media.SIZE);
+        projection.add(MediaStore.Video.Media.DURATION);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            projection.add(MediaStore.Video.Media.WIDTH);
+            projection.add(MediaStore.Video.Media.HEIGHT);
+        }
+        String selection = null;
+        String[] selectionArgs = null;
+        if (!TextUtils.equals(bucketId, String.valueOf(Integer.MIN_VALUE))) {
+            selection = MediaStore.Video.Media.BUCKET_ID + "=?";
+            selectionArgs = new String[]{bucketId};
+        }
+
+        Cursor cursor = contentResolver.query(
+                MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), selection,
+                selectionArgs, MediaStore.Video.Media.DATE_ADDED + " DESC LIMIT " + limit + " OFFSET " + offset);
+        if (cursor != null) {
+            int count = cursor.getCount();
+            if (count > 0) {
+                cursor.moveToFirst();
+                do {
+                    MediaBean mediaBean = parseVideoCursorAndCreateThumImage(context, cursor);
+                    mediaBeanList.add(mediaBean);
+                } while (cursor.moveToNext());
+            }
+        }
+
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
+        }
+        return mediaBeanList;
+    }
+
+    /**
+     * 根据原图获取图片相关信息
+     */
+    public static MediaBean getMediaBeanWithImage(Context context, String originalPath) {
+        ContentResolver contentResolver = context.getContentResolver();
+        List<String> projection = new ArrayList<>();
+        projection.add(MediaStore.Images.Media._ID);
+        projection.add(MediaStore.Images.Media.TITLE);
+        projection.add(MediaStore.Images.Media.DATA);
+        projection.add(MediaStore.Images.Media.BUCKET_ID);
+        projection.add(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
+        projection.add(MediaStore.Images.Media.MIME_TYPE);
+        projection.add(MediaStore.Images.Media.DATE_ADDED);
+        projection.add(MediaStore.Images.Media.DATE_MODIFIED);
+        projection.add(MediaStore.Images.Media.LATITUDE);
+        projection.add(MediaStore.Images.Media.LONGITUDE);
+        projection.add(MediaStore.Images.Media.ORIENTATION);
+        projection.add(MediaStore.Images.Media.SIZE);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            projection.add(MediaStore.Images.Media.WIDTH);
+            projection.add(MediaStore.Images.Media.HEIGHT);
+        }
+        Cursor cursor = contentResolver.query(
+                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection.toArray(new String[projection.size()]), MediaStore.Images.Media.DATA + "=?",
+                new String[]{originalPath}, null);
+        MediaBean mediaBean = null;
+        if (cursor != null && cursor.getCount() > 0) {
+            cursor.moveToFirst();
+            mediaBean = parseImageCursorAndCreateThumImage(context, cursor);
+        }
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
+        }
+        return mediaBean;
+    }
+
+    /**
+     * 根据地址获取视频相关信息
+     */
+    public static MediaBean getMediaBeanWithVideo(Context context, String originalPath) {
+        ContentResolver contentResolver = context.getContentResolver();
+        List<String> projection = new ArrayList<>();
+        projection.add(MediaStore.Video.Media._ID);
+        projection.add(MediaStore.Video.Media.TITLE);
+        projection.add(MediaStore.Video.Media.DATA);
+        projection.add(MediaStore.Video.Media.BUCKET_ID);
+        projection.add(MediaStore.Video.Media.BUCKET_DISPLAY_NAME);
+        projection.add(MediaStore.Video.Media.MIME_TYPE);
+        projection.add(MediaStore.Video.Media.DATE_ADDED);
+        projection.add(MediaStore.Video.Media.DATE_MODIFIED);
+        projection.add(MediaStore.Video.Media.LATITUDE);
+        projection.add(MediaStore.Video.Media.LONGITUDE);
+        projection.add(MediaStore.Video.Media.SIZE);
+        projection.add(MediaStore.Video.Media.DURATION);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            projection.add(MediaStore.Video.Media.WIDTH);
+            projection.add(MediaStore.Video.Media.HEIGHT);
+        }
+        Cursor cursor = contentResolver.query(
+                MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                projection.toArray(new String[projection.size()]),
+                MediaStore.Images.Media.DATA + "=?",
+                new String[]{originalPath}, null);
+        MediaBean mediaBean = null;
+        if (cursor != null && cursor.getCount() > 0) {
+            cursor.moveToFirst();
+            mediaBean = parseVideoCursorAndCreateThumImage(context, cursor);
+        }
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
+        }
+        return mediaBean;
+    }
+
+
+    /**
+     * 解析图片cursor并且创建缩略图
+     * <p>
+     * update 17.07.23 log
+     * <p>
+     * 判断图片 Size ,如果小于等于0则返回 Null,避免出现 No such file or directory
+     */
+    @Nullable
+    private static MediaBean parseImageCursorAndCreateThumImage(Context context, Cursor cursor) {
+        long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
+        String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
+        if (TextUtils.isEmpty(originalPath) || size <= 0 || !new File(originalPath).exists()) {
+            return null;
+        }
+
+        long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
+        String title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.TITLE));
+        String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
+        String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
+        String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE));
+        long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
+        long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED));
+
+        MediaBean mediaBean = new MediaBean();
+        mediaBean.setId(id);
+        mediaBean.setTitle(title);
+        mediaBean.setOriginalPath(originalPath);
+        mediaBean.setBucketId(bucketId);
+        mediaBean.setBucketDisplayName(bucketDisplayName);
+        mediaBean.setMimeType(mimeType);
+        mediaBean.setCreateDate(createDate);
+        mediaBean.setModifiedDate(modifiedDate);
+        mediaBean.setThumbnailBigPath(createThumbnailBigFileName(context, originalPath).getAbsolutePath());
+        mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath());
+        int width = 0, height = 0;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            width = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.WIDTH));
+            height = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT));
+        } else {
+            try {
+                ExifInterface exifInterface = new ExifInterface(originalPath);
+                width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0);
+                height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0);
+            } catch (IOException e) {
+//                Logger.e(e);
+            }
+        }
+        mediaBean.setWidth(width);
+        mediaBean.setHeight(height);
+        double latitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Images.Media.LATITUDE));
+        mediaBean.setLatitude(latitude);
+        double longitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Images.Media.LONGITUDE));
+        mediaBean.setLongitude(longitude);
+        int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION));
+        mediaBean.setOrientation(orientation);
+        long length = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
+        mediaBean.setLength(length);
+
+        return mediaBean;
+    }
+
+    /**
+     * 解析视频cursor并且创建缩略图
+     */
+    private static MediaBean parseVideoCursorAndCreateThumImage(Context context, Cursor cursor) {
+        MediaBean mediaBean = new MediaBean();
+        long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media._ID));
+        mediaBean.setId(id);
+        String title = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.TITLE));
+        mediaBean.setTitle(title);
+        String originalPath = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
+        mediaBean.setOriginalPath(originalPath);
+        String bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID));
+        mediaBean.setBucketId(bucketId);
+        String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME));
+        mediaBean.setBucketDisplayName(bucketDisplayName);
+        String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.MIME_TYPE));
+        mediaBean.setMimeType(mimeType);
+        long createDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED));
+        mediaBean.setCreateDate(createDate);
+        long modifiedDate = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.DATE_MODIFIED));
+        mediaBean.setModifiedDate(modifiedDate);
+        long length = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.SIZE));
+        mediaBean.setLength(length);
+        long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.DURATION));
+        mediaBean.setDuration(duration);
+
+        //创建缩略图文件
+        mediaBean.setThumbnailBigPath(createThumbnailBigFileName(context, originalPath).getAbsolutePath());
+        mediaBean.setThumbnailSmallPath(createThumbnailSmallFileName(context, originalPath).getAbsolutePath());
+
+        int width = 0, height = 0;
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+            width = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.WIDTH));
+            height = cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.HEIGHT));
+        } else {
+            try {
+                ExifInterface exifInterface = new ExifInterface(originalPath);
+                width = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, 0);
+                height = exifInterface.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, 0);
+            } catch (IOException e) {
+//                Logger.e(e);
+            }
+        }
+        mediaBean.setWidth(width);
+        mediaBean.setHeight(height);
+
+        double latitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Video.Media.LATITUDE));
+        mediaBean.setLatitude(latitude);
+        double longitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Video.Media.LONGITUDE));
+        mediaBean.setLongitude(longitude);
+        return mediaBean;
+    }
+
+    public static File createThumbnailBigFileName(Context context, String originalPath) {
+        File storeFile = StorageUtils.getCacheDirectory(context);
+        return new File(storeFile, "big_" + FilenameUtils.getName(originalPath));
+    }
+
+    public static File createThumbnailSmallFileName(Context context, String originalPath) {
+        File storeFile = StorageUtils.getCacheDirectory(context);
+        return new File(storeFile, "small_" + FilenameUtils.getName(originalPath));
+    }
+
+    /**
+     * 获取所有的图片文件夹
+     */
+    public static List<BucketBean> getAllBucketByImage(Context context) {
+        return getAllBucket(context, true);
+    }
+
+    /**
+     * 获取所以视频文件夹
+     */
+    public static List<BucketBean> getAllBucketByVideo(Context context) {
+        return getAllBucket(context, false);
+    }
+
+    /**
+     * 获取所有的问media文件夹
+     */
+    public static List<BucketBean> getAllBucket(Context context, boolean isImage) {
+        List<BucketBean> bucketBeenList = new ArrayList<>();
+        ContentResolver contentResolver = context.getContentResolver();
+        String[] projection;
+        if (isImage) {
+            projection = new String[]{
+                    MediaStore.Images.Media.BUCKET_ID,
+                    MediaStore.Images.Media.DATA,
+                    MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
+                    MediaStore.Images.Media.ORIENTATION,
+            };
+        } else {
+            projection = new String[]{
+                    MediaStore.Video.Media.BUCKET_ID,
+                    MediaStore.Video.Media.DATA,
+                    MediaStore.Video.Media.BUCKET_DISPLAY_NAME,
+            };
+        }
+        BucketBean allMediaBucket = new BucketBean();
+        allMediaBucket.setBucketId(String.valueOf(Integer.MIN_VALUE));
+        Uri uri;
+        if (isImage) {
+            allMediaBucket.setBucketName("所有图片");
+            uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+        } else {
+            allMediaBucket.setBucketName("所有视频");
+            uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+        }
+        bucketBeenList.add(allMediaBucket);
+        Cursor cursor = null;
+        try {
+            cursor = contentResolver.query(uri, projection, null, null, MediaStore.Video.Media.DATE_ADDED + " DESC");
+        } catch (Exception e) {
+//            Logger.e(e);
+        }
+
+        if (cursor != null && cursor.getCount() > 0) {
+            cursor.moveToFirst();
+            do {
+                BucketBean bucketBean = new BucketBean();
+                String bucketId;
+                String bucketKey;
+                String cover;
+                if (isImage) {
+                    bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_ID));
+                    bucketBean.setBucketId(bucketId);
+                    String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.BUCKET_DISPLAY_NAME));
+                    bucketBean.setBucketName(bucketDisplayName);
+                    bucketKey = MediaStore.Images.Media.BUCKET_ID;
+                    cover = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
+                    int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.ORIENTATION));
+                    bucketBean.setOrientation(orientation);
+                } else {
+                    bucketId = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_ID));
+                    bucketBean.setBucketId(bucketId);
+                    String bucketDisplayName = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.BUCKET_DISPLAY_NAME));
+                    bucketBean.setBucketName(bucketDisplayName);
+                    bucketKey = MediaStore.Video.Media.BUCKET_ID;
+                    cover = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
+                }
+                if (TextUtils.isEmpty(allMediaBucket.getCover())) {
+                    allMediaBucket.setCover(cover);
+                }
+                if (bucketBeenList.contains(bucketBean)) {
+                    continue;
+                }
+                //获取数量
+                Cursor c = contentResolver.query(uri, projection, bucketKey + "=?", new String[]{bucketId}, null);
+                if (c != null && c.getCount() > 0) {
+                    bucketBean.setImageCount(c.getCount());
+                }
+                bucketBean.setCover(cover);
+                if (c != null && !c.isClosed()) {
+                    c.close();
+                }
+                bucketBeenList.add(bucketBean);
+            } while (cursor.moveToNext());
+        }
+
+        if (cursor != null && !cursor.isClosed()) {
+            cursor.close();
+        }
+        return bucketBeenList;
+    }
+
+    public static String openCamera(Activity activity, boolean isImage) {
+        Intent captureIntent = isImage ? new Intent(MediaStore.ACTION_IMAGE_CAPTURE) : new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
+        if (captureIntent.resolveActivity(activity.getPackageManager()) == null) {
+            Toast.makeText(SheepApp.getInstance(), "相机不可用", Toast.LENGTH_SHORT).show();
+            return null;
+        }
+
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
+        String filename = String.format(isImage ? IMAGE_STORE_FILE_NAME : VIDEO_STORE_FILE_NAME, dateFormat.format(new Date()));
+        File fileImagePath = new File(ClassFileHelper.DIR, filename);
+        String mImagePath = fileImagePath.getAbsolutePath();
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(fileImagePath));
+        } else {
+            ContentValues contentValues = new ContentValues(1);
+            contentValues.put(MediaStore.Images.Media.DATA, mImagePath);
+            Uri uri = SheepApp.getInstance().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
+            captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
+        }
+        // video : 1: 高质量  0 低质量
+        //        captureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
+        activity.startActivityForResult(captureIntent, isImage ? TAKE_IMAGE_REQUEST_CODE : TAKE_VIDEO_REQUEST_CODE);
+        return mImagePath;
+    }
+
+    public static void onActivityResult(Activity activity, int requestCode, String path, CameraCallBack cameraCallBack) {
+        Log.i(MediaUtils.class.getSimpleName(), "onActivityResult: requestCode=" + requestCode);
+        switch (requestCode) {
+            case TAKE_IMAGE_REQUEST_CODE:
+                if (path == null) {
+                    Log.i(MediaUtils.class.getSimpleName(), "拍照成功");
+                    cameraCallBack.onGetImageSuccess(null);
+                    break;
+                }
+                String cropFilePath = path.substring(0, path.lastIndexOf(".")) + "temp.png";
+                Log.i(MediaUtils.class.getSimpleName(), "拍照成功: " + cropFilePath);
+                cameraCallBack.onGetImageSuccess(cropFilePath);
+                UCrop.of(Uri.parse(path), Uri.parse(cropFilePath))
+                        .start(activity);
+                break;
+            case TAKE_VIDEO_REQUEST_CODE:
+                Log.i(MediaUtils.class.getSimpleName(), "摄像成功");
+                cameraCallBack.onGetVideoSuccess();
+                break;
+            case UCrop.REQUEST_CROP:
+                Log.i(MediaUtils.class.getSimpleName(), "裁剪成功");
+                cameraCallBack.onCropImageSuccess();
+                break;
+        }
+    }
+
+    public static final String IMAGE_STORE_FILE_NAME = "IMG_%s.jpg";
+    public static final String VIDEO_STORE_FILE_NAME = "IMG_%s.mp4";
+    public static final int TAKE_IMAGE_REQUEST_CODE = 1001;
+    public static final int TAKE_VIDEO_REQUEST_CODE = 1002;
+}

+ 170 - 0
app/src/main/java/cn/finalteam/rxgalleryfinal/utils/StorageUtils.java

@@ -0,0 +1,170 @@
+package cn.finalteam.rxgalleryfinal.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+
+import java.io.File;
+import java.io.IOException;
+
+import static android.os.Environment.MEDIA_MOUNTED;
+
+/**
+ * Provides application storage paths
+ *
+ * @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
+ * @since 1.0.0
+ */
+public final class StorageUtils {
+
+    private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
+    private static final String INDIVIDUAL_DIR_NAME = "rxgalleryfinal";
+
+    private StorageUtils() {
+    }
+
+    /**
+     * Returns application cache directory. Cache directory will be created on SD card
+     * <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted and app has appropriate permission. Else -
+     * Android defines cache directory on device's file system.
+     *
+     * @param context Application context
+     * @return Cache {@link File directory}.<br />
+     * <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
+     * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+     */
+    public static File getCacheDirectory(Context context) {
+        return getCacheDirectory(context, true);
+    }
+
+    /**
+     * Returns application cache directory. Cache directory will be created on SD card
+     * <i>("/Android/data/[app_package_name]/cache")</i> (if card is mounted and app has appropriate permission) or
+     * on device's file system depending incoming parameters.
+     *
+     * @param context        Application context
+     * @param preferExternal Whether prefer external location for cache
+     * @return Cache {@link File directory}.<br />
+     * <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
+     * {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
+     */
+    public static File getCacheDirectory(Context context, boolean preferExternal) {
+        File appCacheDir = null;
+
+        if (preferExternal && existSDcard() && hasExternalStoragePermission(context)) {
+            appCacheDir = getExternalCacheDir(context);
+        }
+        if (appCacheDir == null) {
+            appCacheDir = context.getCacheDir();
+        }
+        if (appCacheDir == null) {
+            @SuppressLint("SdCardPath") String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
+//            Logger.w(String.format("Can't define system cache directory! '%s' will be used.", cacheDirPath));
+            appCacheDir = new File(cacheDirPath);
+        }
+        return appCacheDir;
+    }
+
+    public static boolean existSDcard() {
+        String externalStorageState;
+        try {
+            externalStorageState = Environment.getExternalStorageState();
+        } catch (NullPointerException e) { // (sh)it happens (Issue #660)
+            externalStorageState = "";
+        }
+        return MEDIA_MOUNTED.equals(externalStorageState);
+    }
+
+    /**
+     * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
+     * created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted and app has
+     * appropriate permission. Else - Android defines cache directory on device's file system.
+     *
+     * @param context Application context
+     * @return Cache {@link File directory}
+     */
+    public static File getIndividualCacheDirectory(Context context) {
+        return getIndividualCacheDirectory(context, INDIVIDUAL_DIR_NAME);
+    }
+
+    /**
+     * Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
+     * created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted and app has
+     * appropriate permission. Else - Android defines cache directory on device's file system.
+     *
+     * @param context  Application context
+     * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
+     * @return Cache {@link File directory}
+     */
+    public static File getIndividualCacheDirectory(Context context, String cacheDir) {
+        File appCacheDir = getCacheDirectory(context);
+        File individualCacheDir = new File(appCacheDir, cacheDir);
+        if (!individualCacheDir.exists()) {
+            if (!individualCacheDir.mkdir()) {
+                individualCacheDir = appCacheDir;
+            }
+        }
+        return individualCacheDir;
+    }
+
+    /**
+     * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
+     * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system.
+     *
+     * @param context  Application context
+     * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
+     * @return Cache {@link File directory}
+     */
+    public static File getOwnCacheDirectory(Context context, String cacheDir) {
+        File appCacheDir = null;
+        if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
+            appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
+        }
+        if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
+            appCacheDir = context.getCacheDir();
+        }
+        return appCacheDir;
+    }
+
+    /**
+     * Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
+     * is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system.
+     *
+     * @param context  Application context
+     * @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
+     * @return Cache {@link File directory}
+     */
+    public static File getOwnCacheDirectory(Context context, String cacheDir, boolean preferExternal) {
+        File appCacheDir = null;
+        if (preferExternal && MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
+            appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
+        }
+        if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
+            appCacheDir = context.getCacheDir();
+        }
+        return appCacheDir;
+    }
+
+    private static File getExternalCacheDir(Context context) {
+        File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
+        File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
+        if (!appCacheDir.exists()) {
+            if (!appCacheDir.mkdirs()) {
+//                Logger.w("Unable to create external cache directory");
+                return null;
+            }
+            try {
+                new File(appCacheDir, ".nomedia").createNewFile();
+            } catch (IOException e) {
+//                Logger.i("Can't create \".nomedia\" file in application external cache directory");
+            }
+        }
+        return appCacheDir;
+    }
+
+    private static boolean hasExternalStoragePermission(Context context) {
+        int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
+        return perm == PackageManager.PERMISSION_GRANTED;
+    }
+}

+ 9 - 0
app/src/main/java/com/kfzs/duanduan/utils/NumberFormatUtils.java

@@ -92,6 +92,15 @@ public class NumberFormatUtils {
     }
     }
 
 
     /**
     /**
+     * 最多保留一位小数
+     * @param bonus
+     * @return
+     */
+    public static String retainMost1(double bonus) {
+        DecimalFormat df = new DecimalFormat("#.#");
+        return df.format(bonus);
+    }
+    /**
      * 最多保留两位小数
      * 最多保留两位小数
      * @param bonus
      * @param bonus
      * @return
      * @return

+ 7 - 4
app/src/main/java/com/kfzs/duanduan/view/DialogStorageLow.java

@@ -1,12 +1,15 @@
 package com.kfzs.duanduan.view;
 package com.kfzs.duanduan.view;
 
 
+import android.app.Activity;
 import android.content.Context;
 import android.content.Context;
 import android.content.Intent;
 import android.content.Intent;
 import android.provider.Settings;
 import android.provider.Settings;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
 import android.view.View;
 import android.view.View;
 
 
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.DialogConfig;
+import com.sheep.gamegroup.util.ActivityManager;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 
 
@@ -17,15 +20,15 @@ import com.sheep.jiuyan.samllsheep.SheepApp;
 
 
 public class DialogStorageLow {
 public class DialogStorageLow {
 
 
-    public static AlertDialog showDialog(Context context) {
-        final Context mContext = context == null ? SheepApp.getInstance() : context;
-        return ViewUtil.showMsgDialog(mContext, new DialogConfig().setTitle("温馨提示").setMsgMore("存储空间不足\n请释放一些储存空间,并重新尝试安装!")
+    public static AlertDialog showDialog(String msgMore) {
+        final Activity activity = ActivityManager.getInstance().currentActivity();
+        return ViewUtil.showMsgDialog(activity, new DialogConfig().setTitle("温馨提示").setMsgMore("存储空间不足\n请释放一些储存空间,并重新尝试安装!" + (TextUtils.isEmpty(msgMore) ? "" : ("\n"+msgMore)))
             .setBtnRightText("取消").setBtnLeftText("管理应用").setBtnLeftOnClickListener(new View.OnClickListener() {
             .setBtnRightText("取消").setBtnLeftText("管理应用").setBtnLeftOnClickListener(new View.OnClickListener() {
                     @Override
                     @Override
                     public void onClick(View view) {
                     public void onClick(View view) {
                         Intent intent = new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
                         Intent intent = new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        mContext.startActivity(intent);
+                        activity.startActivity(intent);
                     }
                     }
                 }));
                 }));
     }
     }

+ 75 - 0
app/src/main/java/com/sheep/gamegroup/absBase/AbsApiRefresh.java

@@ -0,0 +1,75 @@
+package com.sheep.gamegroup.absBase;
+
+import com.alibaba.fastjson.JSONObject;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.view.fragment.BaseListFragment6;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.sheep.gamegroup.util.DataUtil.PER_PAGE;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ */
+public abstract class AbsApiRefresh<T> implements IApiRefresh {
+
+    public AbsApiRefresh(BaseListFragment6 baseListFragment6) {
+        this.baseListFragment6 = baseListFragment6;
+    }
+
+    protected List<T> list = new ArrayList<>();
+    private BaseListFragment6 baseListFragment6;
+    protected int page = 1;
+    protected int per_page = PER_PAGE;
+    private boolean loadMore = false;
+
+    @Override
+    public void setLoadMore(boolean loadMore) {
+        this.loadMore = loadMore;
+    }
+
+    //还有数据没有获取
+    protected boolean hasMore() {
+        return ListUtil.size(list) >= per_page * page;
+    }
+
+    protected void loadList(List<T> newList) {
+        LogUtil.println(AbsApiRefresh.class.getSimpleName(), "loadList", JSONObject.toJSONString(newList));
+        list.addAll(newList);
+        notifyDataSetChanged();
+    }
+
+    private void notifyDataSetChanged() {
+        if (baseListFragment6 != null)
+            baseListFragment6.notifyDataSetChanged(page, hasMore());
+    }
+
+    @Override
+    public void clear() {
+        list.clear();
+        page = 1;
+    }
+
+    @Override
+    public void loadMoreData() {
+        if (!loadMore) {
+            loadMore = true;
+            if (hasMore()) {
+                page += 1;
+                LogUtil.println(AbsApiRefresh.class.getSimpleName(), "loadMoreData", "hasMore", page);
+                initData();
+            } else {
+                LogUtil.println(AbsApiRefresh.class.getSimpleName(), "loadMoreData", "noMore", page);
+                notifyDataSetChanged();
+            }
+        }
+    }
+
+    @Override
+    public List<T> getList() {
+        return list;
+    }
+}

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

@@ -1,5 +1,8 @@
 package com.sheep.gamegroup.absBase;
 package com.sheep.gamegroup.absBase;
 
 
+import com.sheep.gamegroup.util.TestUtil;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
 import io.reactivex.Observer;
 import io.reactivex.Observer;
 import io.reactivex.disposables.Disposable;
 import io.reactivex.disposables.Disposable;
 
 
@@ -20,7 +23,7 @@ public abstract class AbsObserver<T> implements Observer<T> {
 
 
     @Override
     @Override
     public void onError(Throwable e) {
     public void onError(Throwable e) {
-
+        if(TestUtil.isDev()) G.showToast(e.getMessage());
     }
     }
 
 
     @Override
     @Override

+ 9 - 0
app/src/main/java/com/sheep/gamegroup/absBase/BaseActivity.java

@@ -7,6 +7,8 @@ import com.sheep.gamegroup.util.ActionUtil;
 import com.sheep.gamegroup.view.dialog.DialogLoading;
 import com.sheep.gamegroup.view.dialog.DialogLoading;
 import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
 import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
 
 
+import org.greenrobot.eventbus.EventBus;
+
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 
 
 import butterknife.ButterKnife;
 import butterknife.ButterKnife;
@@ -23,6 +25,9 @@ public abstract class BaseActivity extends RxAppCompatActivity {
 
 
     protected DialogLoading dialogLoading;
     protected DialogLoading dialogLoading;
     public Unbinder unbinder;
     public Unbinder unbinder;
+    protected boolean needRegisterEventBus(){
+        return false;
+    }
     protected boolean needButterKnife(){
     protected boolean needButterKnife(){
         return true;
         return true;
     }
     }
@@ -32,6 +37,8 @@ public abstract class BaseActivity extends RxAppCompatActivity {
         setContentView(getLayoutId());
         setContentView(getLayoutId());
         if(needButterKnife())
         if(needButterKnife())
             unbinder = ButterKnife.bind(this);
             unbinder = ButterKnife.bind(this);
+        if(needRegisterEventBus())
+            EventBus.getDefault().register(this);
         initView();
         initView();
         initListener();
         initListener();
         initData();
         initData();
@@ -111,5 +118,7 @@ public abstract class BaseActivity extends RxAppCompatActivity {
         } catch (Exception e) {
         } catch (Exception e) {
             e.printStackTrace();
             e.printStackTrace();
         }
         }
+        if(needRegisterEventBus())
+            EventBus.getDefault().unregister(this);
     }
     }
 }
 }

+ 48 - 0
app/src/main/java/com/sheep/gamegroup/absBase/CheckErrorApiRefresh.java

@@ -0,0 +1,48 @@
+package com.sheep.gamegroup.absBase;
+
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.view.fragment.BaseListFragment6;
+
+import java.util.List;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ * 可以排除无效数据
+ */
+public abstract class CheckErrorApiRefresh<T> extends AbsApiRefresh<T> {
+
+    public CheckErrorApiRefresh(BaseListFragment6 baseListFragment6) {
+        super(baseListFragment6);
+    }
+
+    private int errorCount = 0;//错误数据个数
+
+    @Override
+    public void clear() {
+        errorCount = 0;
+        super.clear();
+    }
+
+    @Override
+    protected void loadList(List<T> newList) {
+        ListUtil.removeItem(newList, new ListUtil.CallBack<T, Boolean>() {
+            @Override
+            public Boolean call(T mediaBean) {
+                boolean result = isRightData(mediaBean);
+                if (!result) {//错误数据,删除,并记录个数
+                    errorCount++;
+                }
+                return !result;
+            }
+        });
+        super.loadList(newList);
+    }
+
+    protected abstract boolean isRightData(T item);
+
+    @Override
+    protected boolean hasMore() {//有错误数据,删除后翻页就不正常了,要加上
+        return ListUtil.size(list) + errorCount >= per_page * page;
+    }
+}

+ 19 - 0
app/src/main/java/com/sheep/gamegroup/absBase/IApiRefresh.java

@@ -0,0 +1,19 @@
+package com.sheep.gamegroup.absBase;
+
+import java.util.List;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ */
+public interface IApiRefresh<T> {
+    void setLoadMore(boolean loadMore);
+
+    void initData();
+
+    void clear();
+
+    void loadMoreData();
+
+    List<T> getList();
+}

+ 22 - 9
app/src/main/java/com/sheep/gamegroup/absBase/ApiRefresh.java

@@ -18,8 +18,8 @@ import io.reactivex.schedulers.Schedulers;
  * Created by realicing on 2018/11/28.
  * Created by realicing on 2018/11/28.
  * realicing@sina.com
  * realicing@sina.com
  */
  */
-public abstract class ApiRefresh<T> {
-    public ApiRefresh(BaseListFragment6<?> baseListFragment6) {
+public abstract class NetApiRefresh<T> implements IApiRefresh {
+    public NetApiRefresh(BaseListFragment6<?> baseListFragment6) {
         this.baseListFragment6 = baseListFragment6;
         this.baseListFragment6 = baseListFragment6;
     }
     }
 
 
@@ -49,22 +49,27 @@ public abstract class ApiRefresh<T> {
         return lastMessage;
         return lastMessage;
     }
     }
 
 
-    public boolean loadMoreData() {
+    public void loadMoreData() {
         if (!loadMore) {
         if (!loadMore) {
             loadMore = true;
             loadMore = true;
-            if (ListUtil.size(list) >= per_page * page) {
+            if (hasMore()) {
                 page += 1;
                 page += 1;
                 initData();
                 initData();
             } else {
             } else {
                 if (baseListFragment6 != null)
                 if (baseListFragment6 != null)
-                    baseListFragment6.setNoMore(true);
+                    baseListFragment6.notifyDataSetChanged(page, hasMore());
             }
             }
-            return false;
-        } else {
-            return true;
         }
         }
     }
     }
 
 
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
+
     public void clear() {
     public void clear() {
         lastMessage = null;
         lastMessage = null;
         list.clear();
         list.clear();
@@ -108,7 +113,7 @@ public abstract class ApiRefresh<T> {
 
 
     private void notifyDataSetChanged() {
     private void notifyDataSetChanged() {
         if (baseListFragment6 != null)
         if (baseListFragment6 != null)
-            baseListFragment6.notifyDataSetChanged();
+            baseListFragment6.notifyDataSetChanged(page, hasMore());
     }
     }
 
 
     protected List<T> newList;
     protected List<T> newList;
@@ -122,4 +127,12 @@ public abstract class ApiRefresh<T> {
     public void setLoadMore(boolean loadMore) {
     public void setLoadMore(boolean loadMore) {
         this.loadMore = loadMore;
         this.loadMore = loadMore;
     }
     }
+
+    public boolean hasPosition(int position){
+        return ListUtil.hasIndex(list, position);
+    }
+
+    public T getItem(int position){
+        return ListUtil.getItem(list, position);
+    }
 }
 }

+ 119 - 0
app/src/main/java/com/sheep/gamegroup/find/activity/ActMediaChoose.java

@@ -0,0 +1,119 @@
+package com.sheep.gamegroup.find.activity;
+
+
+import android.app.Activity;
+import android.content.Intent;
+import android.support.annotation.Nullable;
+import android.support.design.widget.TabLayout;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+import com.sheep.gamegroup.absBase.BaseActivity;
+import com.sheep.gamegroup.absBase.IRefresh;
+import com.sheep.gamegroup.find.fragment.FgtMediaPickerImg;
+import com.sheep.gamegroup.find.fragment.FgtMediaPickerVideo;
+import com.sheep.gamegroup.util.CommonUtil;
+import com.sheep.gamegroup.util.DataUtil;
+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 butterknife.BindView;
+import cn.finalteam.rxgalleryfinal.api.CameraCallBack;
+import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
+
+import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
+import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_NONE;
+import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
+
+/**
+ * Created by realicing on 2018/11/26.
+ * realicing@sina.com
+ * 小绵羊3.4.5新增--发布发现内容--选择视频和图片
+ */
+public class ActMediaChoose extends BaseActivity {
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.act_media_choose;
+    }
+
+    @BindView(R.id.indicator)
+    TabLayout indicator;
+    @BindView(R.id.below_tab_line)
+    View below_tab_line;
+    @BindView(R.id.viewPager)
+    ViewPager viewPager;
+
+    private TitleFragmentListAdapter mAdapter;
+    @Override
+    public void initView() {
+        TitleBarUtils.getInstance().setTitle(this, "选择媒体")
+                .setTitleFinish(this).setRightImgBotton(this, R.mipmap.ic_open_camera, new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+//                Jump2View.getInstance().goActEditVideo(video);
+                boolean isVideo = mAdapter.getItem(viewPager.getCurrentItem()) instanceof FgtMediaPickerVideo;
+                MediaUtils.openCamera(ActMediaChoose.this, !isVideo);
+            }
+        });
+
+        mAdapter = new TitleFragmentListAdapter(getSupportFragmentManager());
+        mAdapter.add(new FgtMediaPickerVideo(), "视频");
+        if(TestUtil.isDev()) {
+            mAdapter.add(new FgtMediaPickerImg(), "图片");
+        }
+        viewPager.setAdapter(mAdapter);
+        indicator.setupWithViewPager(viewPager);
+        viewPager.setCurrentItem(0);
+        viewPager.setOffscreenPageLimit(mAdapter.getCount());
+        CommonUtil.getInstance().reflex(indicator, this);
+        if(mAdapter.getCount() < 2){
+            ViewUtil.setVisibility(indicator, false);
+            ViewUtil.setVisibility(below_tab_line, false);
+        }
+//        Integer type = DataUtil.getObject(getIntent(), Integer.class);
+//        if(type != null){
+//            switch (type){
+//                case MEDIA_TYPE_IMAGE:
+//                    break;
+//                case MEDIA_TYPE_VIDEO:
+//                    break;
+//                case MEDIA_TYPE_NONE:
+//                default:
+//                    break;
+//            }
+//        }
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
+        if(resultCode == Activity.RESULT_OK){
+            MediaUtils.onActivityResult(this, requestCode, null, new CameraCallBack() {
+                @Override
+                public void onGetImageSuccess(String cropFilePath) {
+                    if(mAdapter.getItem(1) instanceof IRefresh){
+                        ((IRefresh) mAdapter.getItem(1)).refreshData();
+                    }
+                }
+
+                @Override
+                public void onGetVideoSuccess() {
+                    if(mAdapter.getItem(0) instanceof IRefresh){
+                        ((IRefresh) mAdapter.getItem(0)).refreshData();
+                    }
+                }
+
+                @Override
+                public void onCropImageSuccess() {
+                    if(mAdapter.getItem(1) instanceof IRefresh){
+                        ((IRefresh) mAdapter.getItem(1)).refreshData();
+                    }
+                }
+            });
+        }
+    }
+}

+ 109 - 0
app/src/main/java/com/sheep/gamegroup/find/fragment/FgtMediaPickerImg.java

@@ -0,0 +1,109 @@
+package com.sheep.gamegroup.find.fragment;
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.StaggeredGridLayoutManager;
+import android.util.LongSparseArray;
+import android.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.sheep.gamegroup.absBase.AbsApiRefresh;
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.gamegroup.absBase.CheckErrorApiRefresh;
+import com.sheep.gamegroup.absBase.IApiRefresh;
+import com.sheep.gamegroup.model.entity.Lp;
+import com.sheep.gamegroup.util.ViewUtil;
+import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
+import com.sheep.gamegroup.view.fragment.BaseListFragment6;
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
+import java.util.List;
+
+import cn.finalteam.rxgalleryfinal.bean.MediaBean;
+import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/11/27.
+ * realicing@sina.com
+ * 小绵羊3.4.5新增--发布发现内容--选择图片
+ */
+public class FgtMediaPickerImg extends BaseListFragment6<MediaBean> {
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.common_srl_rv;
+    }
+
+    @Override
+    public void initView() {
+        LayoutParamsUtil.resetLayoutParams(recyclerView, new Lp(G.DENSITY).setTbMargin(14).setLrMargin(6));
+    }
+
+    protected LongSparseArray<MediaBean> sparseArray = new LongSparseArray<>();
+    protected LongSparseArray<String> textSparseArray = new LongSparseArray<>();
+
+    private int width = (G.WIDTH - G.getRealPix(48)) / 2;
+
+    @Override
+    protected RecyclerView.LayoutManager getLayoutManager() {
+        return new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
+    }
+
+    @Override
+    protected BaseQuickAdapter<MediaBean, BaseViewHolder> getAdapter() {
+        return new BaseQuickAdapter<MediaBean, BaseViewHolder>(R.layout.item_media_picker, apiRefresh.getList()) {
+
+            @Override
+            protected void convert(BaseViewHolder helper, MediaBean item) {
+                boolean isChoose = sparseArray.get(item.getId()) != null;
+                helper.setText(R.id.item_media_picker_tv, isChoose ? textSparseArray.get(item.getId()) : "√");
+                helper.setBackgroundRes(R.id.item_media_picker_tv, isChoose ? R.drawable.shape_oval_solid_10_main : R.drawable.shape_oval_solid_10_f5);
+                helper.setTextColor(R.id.item_media_picker_tv, SheepApp.getInstance().getResources().getColor(isChoose ? R.color.white : R.color.gray_CBCBCB));
+                ImageView item_media_picker_iv = helper.getView(R.id.item_media_picker_iv);
+                ViewUtil.setViewWH(item_media_picker_iv, width, item.getHeight() * 1.0f / item.getWidth());
+                ViewUtil.setImagePath(item_media_picker_iv, item.getOriginalPath(), G.getRealPix(5));
+            }
+        };
+    }
+
+    private AbsApiRefresh<MediaBean> apiRefresh;
+
+    @Override
+    protected void addApiRefresh(List<IApiRefresh> apiRefreshList) {
+        apiRefresh = new CheckErrorApiRefresh<MediaBean>(this) {
+            @Override
+            protected boolean isRightData(MediaBean item) {
+                return item != null && item.getWidth() > 0 && item.getHeight() > 0;
+            }
+            @Override
+            public void initData() {
+                Observable.create(new ObservableOnSubscribe<List<MediaBean>>() {
+                    @Override
+                    public void subscribe(ObservableEmitter<List<MediaBean>> emitter) {
+                        emitter.onNext(initNewList(page, per_page));
+                    }
+                })
+                        .subscribeOn(Schedulers.io())
+                        .observeOn(AndroidSchedulers.mainThread()).
+                        subscribe(new AbsObserver<List<MediaBean>>() {
+                            @Override
+                            public void onNext(List<MediaBean> newList) {
+                                loadList(newList);
+                            }
+                        });
+            }
+        };
+        apiRefreshList.add(apiRefresh);
+    }
+
+    protected List<MediaBean> initNewList(int page, int per_page) {
+        return MediaUtils.getMediaWithImageList(SheepApp.getInstance(), page, per_page);
+    }
+}

+ 126 - 0
app/src/main/java/com/sheep/gamegroup/find/fragment/FgtMediaPickerVideo.java

@@ -0,0 +1,126 @@
+package com.sheep.gamegroup.find.fragment;
+
+
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.StaggeredGridLayoutManager;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.sheep.gamegroup.absBase.AbsApiRefresh;
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.gamegroup.absBase.CheckErrorApiRefresh;
+import com.sheep.gamegroup.absBase.IApiRefresh;
+import com.sheep.gamegroup.model.entity.Lp;
+import com.sheep.gamegroup.model.entity.Video;
+import com.sheep.gamegroup.util.Jump2View;
+import com.sheep.gamegroup.util.ListUtil;
+import com.sheep.gamegroup.util.TimeUtil;
+import com.sheep.gamegroup.util.ViewUtil;
+import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
+import com.sheep.gamegroup.view.fragment.BaseListFragment6;
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
+import java.util.List;
+
+import cn.finalteam.rxgalleryfinal.bean.MediaBean;
+import cn.finalteam.rxgalleryfinal.utils.MediaUtils;
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/11/27.
+ * realicing@sina.com
+ * 小绵羊3.4.5新增--发布发现内容--选择视频
+ */
+public class FgtMediaPickerVideo extends BaseListFragment6<MediaBean> {
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.common_srl_rv;
+    }
+
+    @Override
+    public void initView() {
+        LayoutParamsUtil.resetLayoutParams(recyclerView, new Lp(G.DENSITY).setTbMargin(14).setLrMargin(6));
+    }
+
+    private int width = (G.WIDTH - G.getRealPix(48)) / 2;
+
+    @Override
+    protected RecyclerView.LayoutManager getLayoutManager() {
+        return new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
+    }
+
+    @Override
+    protected BaseQuickAdapter<MediaBean, BaseViewHolder> getAdapter() {
+        return new BaseQuickAdapter<MediaBean, BaseViewHolder>(R.layout.item_video, apiRefresh.getList()) {
+
+            @Override
+            protected void convert(BaseViewHolder helper, MediaBean item) {
+                ImageView item_video_cover = helper.getView(R.id.item_video_cover);
+                TextView item_video_time_tv = helper.itemView.findViewById(R.id.item_video_time_tv);
+                ViewUtil.setViewWH(item_video_cover, width, item.getHeight() * 1.0f / item.getWidth());
+                ViewUtil.setImagePath(item_video_cover, item.getOriginalPath(), G.getRealPix(5));
+                ViewUtil.setText(item_video_time_tv, TimeUtil.getDurationText(item.getDuration() / 1000));
+            }
+        };
+    }
+
+    @Override
+    public void initListener() {
+        super.initListener();
+        baseQuickAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+            @Override
+            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));
+            }
+        });
+
+    }
+
+    private AbsApiRefresh<MediaBean> apiRefresh;
+
+    @Override
+    protected void addApiRefresh(List<IApiRefresh> apiRefreshList) {
+        apiRefresh = new CheckErrorApiRefresh<MediaBean>(this) {
+            @Override
+            protected boolean isRightData(MediaBean item) {
+                return item != null && item.getWidth() > 0 && item.getHeight() > 0;
+            }
+
+            @Override
+            public void initData() {
+                Observable.create(new ObservableOnSubscribe<List<MediaBean>>() {
+                    @Override
+                    public void subscribe(ObservableEmitter<List<MediaBean>> emitter) {
+                        emitter.onNext(initNewList(page, per_page));
+                    }
+                })
+                        .subscribeOn(Schedulers.io())
+                        .observeOn(AndroidSchedulers.mainThread()).
+                        subscribe(new AbsObserver<List<MediaBean>>() {
+                            @Override
+                            public void onNext(List<MediaBean> newList) {
+                                loadList(newList);
+                            }
+                        });
+            }
+
+        };
+        apiRefreshList.add(apiRefresh);
+    }
+
+    protected List<MediaBean> initNewList(int page, int per_page) {
+        return MediaUtils.getMediaWithVideoList(SheepApp.getInstance(), page, per_page);
+    }
+}

+ 15 - 0
app/src/main/java/com/sheep/gamegroup/greendao/DDProviderHelper.java

@@ -197,6 +197,21 @@ public class DDProviderHelper {
     /**
     /**
      * 更新任务状态
      * 更新任务状态
      *
      *
+     * @param downloadTaskId
+     * @param downloadUrl
+     */
+    public DownLoadInfo updateDownload(int downloadTaskId, String downloadUrl, int state) {
+        DownLoadInfo downloadTask = getDownloadTask(downloadUrl);
+        if (downloadTask != null) {
+            downloadTask.setMDownloadTaskId(downloadTaskId);
+            downloadTask.setMStatus(state);
+            updateDownload(downloadTask);
+        }
+        return downloadTask;
+    }
+    /**
+     * 更新任务状态
+     *
      * @param downloadedSize
      * @param downloadedSize
      * @param downloadTaskId
      * @param downloadTaskId
      * @param downloadUrl
      * @param downloadUrl

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

@@ -14,10 +14,10 @@ import org.greenrobot.greendao.identityscope.IdentityScopeType;
 
 
 // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
 // THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
 /**
 /**
- * Master of DAO (schema version 14): knows all DAOs.
+ * Master of DAO (schema version 15): knows all DAOs.
  */
  */
 public class DaoMaster extends AbstractDaoMaster {
 public class DaoMaster extends AbstractDaoMaster {
-    public static final int SCHEMA_VERSION = 14;
+    public static final int SCHEMA_VERSION = 15;
 
 
     /** Creates underlying database table using DAOs. */
     /** Creates underlying database table using DAOs. */
     public static void createAllTables(Database db, boolean ifNotExists) {
     public static void createAllTables(Database db, boolean ifNotExists) {

+ 16 - 2
app/src/main/java/com/sheep/gamegroup/greendao/download/DownLoadInfo.java

@@ -125,6 +125,11 @@ public class DownLoadInfo implements Serializable{
      */
      */
     @Property(nameInDb = "average_speed")
     @Property(nameInDb = "average_speed")
     private String averageSpeed;
     private String averageSpeed;
+    /**
+     * 下载速度
+     */
+    @Property(nameInDb = "real_cause_msg")
+    private String realCauseMsg;
 
 
     public int getWhereFrom() {
     public int getWhereFrom() {
         return whereFrom;
         return whereFrom;
@@ -262,12 +267,20 @@ public class DownLoadInfo implements Serializable{
         this.averageSpeed = averageSpeed;
         this.averageSpeed = averageSpeed;
     }
     }
 
 
-    @Generated(hash = 601502121)
+    public String getRealCauseMsg() {
+        return this.realCauseMsg;
+    }
+
+    public void setRealCauseMsg(String realCauseMsg) {
+        this.realCauseMsg = realCauseMsg;
+    }
+
+    @Generated(hash = 74805486)
     public DownLoadInfo(Long mId, Long mCreateTime, Integer mDownloadTaskId,
     public DownLoadInfo(Long mId, Long mCreateTime, Integer mDownloadTaskId,
             String mGameName, String mIconUrl, Integer mPercent, @NotNull Integer mGameID,
             String mGameName, String mIconUrl, Integer mPercent, @NotNull Integer mGameID,
             Double mDownloadedSize, Double mTotalSize, Integer mStatus, String mDownloadUrl,
             Double mDownloadedSize, Double mTotalSize, Integer mStatus, String mDownloadUrl,
             String mChannelDownloadUrl, String mPackageName, Integer mVersionCode,
             String mChannelDownloadUrl, String mPackageName, Integer mVersionCode,
-            String mApkPath, int whereFrom, String averageSpeed) {
+            String mApkPath, int whereFrom, String averageSpeed, String realCauseMsg) {
         this.mId = mId;
         this.mId = mId;
         this.mCreateTime = mCreateTime;
         this.mCreateTime = mCreateTime;
         this.mDownloadTaskId = mDownloadTaskId;
         this.mDownloadTaskId = mDownloadTaskId;
@@ -285,6 +298,7 @@ public class DownLoadInfo implements Serializable{
         this.mApkPath = mApkPath;
         this.mApkPath = mApkPath;
         this.whereFrom = whereFrom;
         this.whereFrom = whereFrom;
         this.averageSpeed = averageSpeed;
         this.averageSpeed = averageSpeed;
+        this.realCauseMsg = realCauseMsg;
     }
     }
 
 
     @Generated(hash = 1743687477)
     @Generated(hash = 1743687477)

+ 16 - 2
app/src/main/java/com/sheep/gamegroup/greendao/download/DownLoadInfoDao.java

@@ -39,6 +39,7 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
         public final static Property MApkPath = new Property(14, String.class, "mApkPath", false, "apk_path");
         public final static Property MApkPath = new Property(14, String.class, "mApkPath", false, "apk_path");
         public final static Property WhereFrom = new Property(15, int.class, "whereFrom", false, "where_from");
         public final static Property WhereFrom = new Property(15, int.class, "whereFrom", false, "where_from");
         public final static Property AverageSpeed = new Property(16, String.class, "averageSpeed", false, "average_speed");
         public final static Property AverageSpeed = new Property(16, String.class, "averageSpeed", false, "average_speed");
+        public final static Property RealCauseMsg = new Property(17, String.class, "realCauseMsg", false, "real_cause_msg");
     }
     }
 
 
 
 
@@ -70,7 +71,8 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
                 "\"version_code\" INTEGER," + // 13: mVersionCode
                 "\"version_code\" INTEGER," + // 13: mVersionCode
                 "\"apk_path\" TEXT," + // 14: mApkPath
                 "\"apk_path\" TEXT," + // 14: mApkPath
                 "\"where_from\" INTEGER NOT NULL ," + // 15: whereFrom
                 "\"where_from\" INTEGER NOT NULL ," + // 15: whereFrom
-                "\"average_speed\" TEXT);"); // 16: averageSpeed
+                "\"average_speed\" TEXT," + // 16: averageSpeed
+                "\"real_cause_msg\" TEXT);"); // 17: realCauseMsg
     }
     }
 
 
     /** Drops the underlying database table. */
     /** Drops the underlying database table. */
@@ -159,6 +161,11 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
         if (averageSpeed != null) {
         if (averageSpeed != null) {
             stmt.bindString(17, averageSpeed);
             stmt.bindString(17, averageSpeed);
         }
         }
+ 
+        String realCauseMsg = entity.getRealCauseMsg();
+        if (realCauseMsg != null) {
+            stmt.bindString(18, realCauseMsg);
+        }
     }
     }
 
 
     @Override
     @Override
@@ -241,6 +248,11 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
         if (averageSpeed != null) {
         if (averageSpeed != null) {
             stmt.bindString(17, averageSpeed);
             stmt.bindString(17, averageSpeed);
         }
         }
+ 
+        String realCauseMsg = entity.getRealCauseMsg();
+        if (realCauseMsg != null) {
+            stmt.bindString(18, realCauseMsg);
+        }
     }
     }
 
 
     @Override
     @Override
@@ -267,7 +279,8 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
             cursor.isNull(offset + 13) ? null : cursor.getInt(offset + 13), // mVersionCode
             cursor.isNull(offset + 13) ? null : cursor.getInt(offset + 13), // mVersionCode
             cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14), // mApkPath
             cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14), // mApkPath
             cursor.getInt(offset + 15), // whereFrom
             cursor.getInt(offset + 15), // whereFrom
-            cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16) // averageSpeed
+            cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16), // averageSpeed
+            cursor.isNull(offset + 17) ? null : cursor.getString(offset + 17) // realCauseMsg
         );
         );
         return entity;
         return entity;
     }
     }
@@ -291,6 +304,7 @@ public class DownLoadInfoDao extends AbstractDao<DownLoadInfo, Long> {
         entity.setMApkPath(cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14));
         entity.setMApkPath(cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14));
         entity.setWhereFrom(cursor.getInt(offset + 15));
         entity.setWhereFrom(cursor.getInt(offset + 15));
         entity.setAverageSpeed(cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16));
         entity.setAverageSpeed(cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16));
+        entity.setRealCauseMsg(cursor.isNull(offset + 17) ? null : cursor.getString(offset + 17));
      }
      }
     
     
     @Override
     @Override

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

@@ -1482,7 +1482,7 @@ public interface ApiService {
 
 
     /**
     /**
      * 小绵羊3.4.5新增 -- 用户视频发布
      * 小绵羊3.4.5新增 -- 用户视频发布
-     * UserAddressReqUserAddressReq
+     * CreateUserVideoReq
      */
      */
     @POST("app/video")
     @POST("app/video")
     Observable<BaseMessage> postVideo(@Body JSONObject jsonObject);
     Observable<BaseMessage> postVideo(@Body JSONObject jsonObject);

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

@@ -51,7 +51,7 @@ public class DiscoveryVideo implements Serializable {
 
 
     private int create_time;
     private int create_time;
 
 
-    private int duration;
+    private long duration;
 
 
     private int id;
     private int id;
 
 
@@ -105,10 +105,10 @@ public class DiscoveryVideo implements Serializable {
     public int getCreate_time(){
     public int getCreate_time(){
         return this.create_time;
         return this.create_time;
     }
     }
-    public void setDuration(int duration){
+    public void setDuration(long duration){
         this.duration = duration;
         this.duration = duration;
     }
     }
-    public int getDuration(){
+    public long getDuration(){
         return this.duration;
         return this.duration;
     }
     }
     public void setId(int id){
     public void setId(int id){

+ 36 - 0
app/src/main/java/com/sheep/gamegroup/model/entity/Lp.java

@@ -80,4 +80,40 @@ public class Lp {
         this.height = (int) (height * per);
         this.height = (int) (height * per);
         return this;
         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;
+    }
 }
 }

+ 70 - 0
app/src/main/java/com/sheep/gamegroup/model/entity/Video.java

@@ -0,0 +1,70 @@
+package com.sheep.gamegroup.model.entity;
+
+import java.io.Serializable;
+
+import cn.finalteam.rxgalleryfinal.bean.MediaBean;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ * 视频数据
+ */
+public class Video implements Serializable {
+
+    private int width;//视频宽
+    private int height;//视频高
+    private long duration;//视频长度,单位毫秒
+    private String filePath;//文件对应地址
+    private int topicId;//选择的话题的id
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public void setFilePath(String filePath) {
+        this.filePath = filePath;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public void setWidth(int width) {
+        this.width = width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public void setHeight(int height) {
+        this.height = height;
+    }
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    public int getTopicId() {
+        return topicId;
+    }
+
+    public void setTopicId(int topicId) {
+        this.topicId = topicId;
+    }
+
+
+    //通过MediaBean获取Video
+    public static Video from(MediaBean item) {
+        Video video = new Video();
+        video.setWidth(item.getWidth());
+        video.setHeight(item.getHeight());
+        video.setDuration(item.getDuration());
+        video.setFilePath(item.getOriginalPath());
+        return video;
+    }
+}

+ 25 - 4
app/src/main/java/com/sheep/gamegroup/util/FileUtil.java

@@ -1,5 +1,6 @@
 package com.sheep.gamegroup.util;
 package com.sheep.gamegroup.util;
 
 
+import android.net.Uri;
 import android.text.TextUtils;
 import android.text.TextUtils;
 
 
 import com.sheep.jiuyan.samllsheep.BuildConfig;
 import com.sheep.jiuyan.samllsheep.BuildConfig;
@@ -178,6 +179,7 @@ public class FileUtil {
         }
         }
         return filename;
         return filename;
     }
     }
+
     /*
     /*
      * Java文件操作 获取带扩展名的文件名
      * Java文件操作 获取带扩展名的文件名
      * */
      * */
@@ -195,7 +197,8 @@ public class FileUtil {
 
 
     /**
     /**
      * 获取文件名,带扩展名
      * 获取文件名,带扩展名
-     * @param filename 前提是fileName前面一定没有/
+     *
+     * @param filename  前提是fileName前面一定没有/
      * @param defaultEx 默认的扩展
      * @param defaultEx 默认的扩展
      * @return
      * @return
      */
      */
@@ -212,9 +215,26 @@ public class FileUtil {
     }
     }
 
 
 
 
-
-
-
+    /**
+     * 获取文件名称且不带扩展名
+     *
+     * @param filePath
+     * @return
+     */
+    public static String getFileNameNoExFromPath(String filePath) {
+        if ((filePath != null) && (filePath.length() > 0)) {
+            Uri uri = Uri.parse(filePath);
+            String lastPathSegment = uri.getLastPathSegment();
+            if (lastPathSegment != null) {
+                int dot = lastPathSegment.lastIndexOf('.');
+                if (dot > 0) {
+                    return lastPathSegment.substring(0, dot);
+                }
+                return lastPathSegment;
+            }
+        }
+        return filePath;
+    }
 
 
 
 
     /**
     /**
@@ -225,6 +245,7 @@ public class FileUtil {
     public static void deleteFiles(File pDir) {
     public static void deleteFiles(File pDir) {
         deleteFiles(pDir, true);
         deleteFiles(pDir, true);
     }
     }
+
     /**
     /**
      * 递归删除文件或文件夹。
      * 递归删除文件或文件夹。
      *
      *

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

@@ -16,6 +16,7 @@ import com.danikula.videocache.HttpProxyCacheServer;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.IHomePageSearch;
 import com.sheep.gamegroup.absBase.IHomePageSearch;
 import com.sheep.gamegroup.absBase.IJumpWeb;
 import com.sheep.gamegroup.absBase.IJumpWeb;
+import com.sheep.gamegroup.find.activity.ActMediaChoose;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
 import com.sheep.gamegroup.model.entity.Advertising;
 import com.sheep.gamegroup.model.entity.Advertising;
 import com.sheep.gamegroup.model.entity.Agreement;
 import com.sheep.gamegroup.model.entity.Agreement;
@@ -28,7 +29,6 @@ import com.sheep.gamegroup.model.entity.Container;
 import com.sheep.gamegroup.model.entity.CreditCard;
 import com.sheep.gamegroup.model.entity.CreditCard;
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.DialogEntity;
 import com.sheep.gamegroup.model.entity.DialogEntity;
-import com.sheep.gamegroup.model.entity.DiscoveryVideo;
 import com.sheep.gamegroup.model.entity.GameListTag;
 import com.sheep.gamegroup.model.entity.GameListTag;
 import com.sheep.gamegroup.model.entity.GameListType;
 import com.sheep.gamegroup.model.entity.GameListType;
 import com.sheep.gamegroup.model.entity.HomeListEntity;
 import com.sheep.gamegroup.model.entity.HomeListEntity;
@@ -41,6 +41,7 @@ import com.sheep.gamegroup.model.entity.TaskAcceptedEty;
 import com.sheep.gamegroup.model.entity.TaskEty;
 import com.sheep.gamegroup.model.entity.TaskEty;
 import com.sheep.gamegroup.model.entity.UserEntity;
 import com.sheep.gamegroup.model.entity.UserEntity;
 import com.sheep.gamegroup.model.entity.VersionInfo;
 import com.sheep.gamegroup.model.entity.VersionInfo;
+import com.sheep.gamegroup.model.entity.Video;
 import com.sheep.gamegroup.model.entity.WebviewEntity;
 import com.sheep.gamegroup.model.entity.WebviewEntity;
 import com.sheep.gamegroup.model.entity.XianWanEntity;
 import com.sheep.gamegroup.model.entity.XianWanEntity;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
@@ -53,7 +54,9 @@ import com.sheep.gamegroup.view.activity.ActCoinCenter;
 import com.sheep.gamegroup.view.activity.ActCommentGameApp;
 import com.sheep.gamegroup.view.activity.ActCommentGameApp;
 import com.sheep.gamegroup.view.activity.ActCreditCardTaskList;
 import com.sheep.gamegroup.view.activity.ActCreditCardTaskList;
 import com.sheep.gamegroup.view.activity.ActCreditCardWeb;
 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.view.activity.ActDownloadWelfareList;
+import com.sheep.gamegroup.view.activity.ActEditVideo;
 import com.sheep.gamegroup.view.activity.ActEntertainmentLuckDraw;
 import com.sheep.gamegroup.view.activity.ActEntertainmentLuckDraw;
 import com.sheep.gamegroup.view.activity.ActEveryDayShare;
 import com.sheep.gamegroup.view.activity.ActEveryDayShare;
 import com.sheep.gamegroup.view.activity.ActExchangeCMCC;
 import com.sheep.gamegroup.view.activity.ActExchangeCMCC;
@@ -2257,6 +2260,29 @@ public class Jump2View {
     }
     }
 
 
     /**
     /**
+     * 剪切视频
+     *
+     * @param data 视频数据,包括地址与时长,宽高等
+     */
+    public void goActCutVideo(Video data) {
+        Activity activity = ActivityManager.getInstance().currentActivity();
+        Intent intent = new Intent(activity, ActCutVideo.class);
+        DataUtil.putObject(intent, data);
+        activity.startActivity(intent);
+    }
+    /**
+     * 编辑视频
+     *
+     * @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);
+    }
+
+    /**
      * 提交自定义字段
      * 提交自定义字段
      *
      *
      * @param activity
      * @param activity
@@ -2354,4 +2380,12 @@ public class Jump2View {
         Intent intent = new Intent(activity, ActVideoComment.class);
         Intent intent = new Intent(activity, ActVideoComment.class);
         activity.startActivity(DataUtil.putObject(intent, video_id));
         activity.startActivity(DataUtil.putObject(intent, video_id));
     }
     }
+    /**
+     * 小绵羊3.4.5新增--跳转到选择视频与图片界面
+     */
+    public void gotoActMediaChoose(@ActPublishArticle.Type int type) {
+        Activity activity = ActivityManager.getInstance().currentActivity();
+        Intent intent = new Intent(activity, ActMediaChoose.class);
+        activity.startActivity(DataUtil.putObject(intent, type));
+    }
 }
 }

+ 359 - 0
app/src/main/java/com/sheep/gamegroup/util/MediaHandleUtil.java

@@ -0,0 +1,359 @@
+package com.sheep.gamegroup.util;
+
+import android.media.MediaCodec;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.media.MediaMuxer;
+import android.util.Log;
+
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.gamegroup.model.entity.Video;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.Locale;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/11/30.
+ * realicing@sina.com
+ */
+public class MediaHandleUtil {
+    public static final String TAG = "MediaHandleUtil";
+    private String url;
+    private long clipPoint;
+    private long clipDuration;
+
+    public MediaHandleUtil(String url, long clipPoint, long clipDuration) {
+        this.url = url;
+        this.clipPoint = clipPoint;
+        this.clipDuration = clipDuration;
+    }
+
+    public void tryCutVideo(AbsObserver<Video> absObserver) {
+        Observable.create(new ObservableOnSubscribe<Video>() {
+            @Override
+            public void subscribe(ObservableEmitter<Video> emitter) throws Exception {
+                long time = System.currentTimeMillis();
+                Video video = cutVideo(url, clipPoint, clipDuration);
+                if (video == null) {
+                    emitter.onError(new Throwable("剪切失败"));
+                } else {
+                    emitter.onNext(video);
+                }
+                long curTime = System.currentTimeMillis();
+                LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000);
+            }
+        })
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(absObserver);
+    }
+
+    /**
+     * 获取可以剪切出的视频的地址
+     *
+     * @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));
+    }
+
+    /**
+     * 剪切视频
+     *
+     * @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;
+    }
+
+    public static void mixVideAndAudio(File outVideoPath, File outAudioPath, File outMergeVideoPath) throws Exception {
+        //分别初始化视频、音频的Extractor
+        MediaExtractor videoExtractor = new MediaExtractor();
+        videoExtractor.setDataSource(outVideoPath.getAbsolutePath());
+        MediaExtractor audioExtractor = new MediaExtractor();
+        audioExtractor.setDataSource(outAudioPath.getAbsolutePath());
+        int videoTrack = getTrack(videoExtractor, "video/");
+        int audioTrack = getTrack(audioExtractor, "audio/");
+        videoExtractor.selectTrack(videoTrack);
+        audioExtractor.selectTrack(audioTrack);
+        MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
+        MediaCodec.BufferInfo audioBufferInfo = new MediaCodec.BufferInfo();
+        //写入新的视频
+        if (outMergeVideoPath.exists() && outMergeVideoPath.createNewFile())
+            ;
+        ByteBuffer byteBuffer = ByteBuffer.allocate(500 * 1024);
+
+        MediaMuxer mediaMuxer = new MediaMuxer(outMergeVideoPath.getAbsolutePath(), MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
+        int writeVideoTrackIndex = mediaMuxer.addTrack(videoExtractor.getTrackFormat(videoTrack));
+        int writeAudioTrackIndex = mediaMuxer.addTrack(audioExtractor.getTrackFormat(audioTrack));
+        mediaMuxer.start();
+        long videoSampleTime = getSampleTime(videoExtractor, byteBuffer, videoTrack);
+        while (true) {
+            int data = videoExtractor.readSampleData(byteBuffer, 0);
+            if (data < 0) {
+                break;
+            }
+            videoBufferInfo.size = data;
+            videoBufferInfo.offset = 0;
+            videoBufferInfo.flags = videoExtractor.getSampleFlags();
+            videoBufferInfo.presentationTimeUs += videoSampleTime;
+            mediaMuxer.writeSampleData(writeVideoTrackIndex, byteBuffer, videoBufferInfo);
+            videoExtractor.advance();
+        }
+        long audioSampleTime = getSampleTime(audioExtractor, byteBuffer, audioTrack);
+        while (true) {
+            int data = audioExtractor.readSampleData(byteBuffer, 0);
+            if (data < 0) {
+                break;
+            }
+            audioBufferInfo.size = data;
+            audioBufferInfo.offset = 0;
+            audioBufferInfo.flags = audioExtractor.getSampleFlags();
+            audioBufferInfo.presentationTimeUs += audioSampleTime;
+            mediaMuxer.writeSampleData(writeAudioTrackIndex, byteBuffer, audioBufferInfo);
+            audioExtractor.advance();
+        }
+        Log.i("video", "合并完成");
+        mediaMuxer.stop();
+        mediaMuxer.release();
+        videoExtractor.release();
+        audioExtractor.release();
+    }
+
+    public static long getSampleTime(MediaExtractor mediaExtractor, ByteBuffer byteBuffer, int videoTrack) {
+        mediaExtractor.readSampleData(byteBuffer, 0);
+        //跳过I帧,要P帧(视频是由个别I帧和很多P帧组成)h264编码中有IBP帧 I为关键帧。
+        if (mediaExtractor.getSampleFlags() == MediaExtractor.SAMPLE_FLAG_SYNC) {
+            mediaExtractor.advance();
+        }
+        mediaExtractor.readSampleData(byteBuffer, 0);
+
+        // 得到第一帧的PTS
+        long firstVideoPTS = mediaExtractor.getSampleTime();
+        //下一帧
+        mediaExtractor.advance();
+        mediaExtractor.readSampleData(byteBuffer, 0);
+        long secondVideoPTS = mediaExtractor.getSampleTime();
+        long sampleTime = Math.abs(secondVideoPTS - firstVideoPTS);
+
+        // 重新切换此信道,不然上面跳过了3帧,造成前面的帧数模糊
+        mediaExtractor.unselectTrack(videoTrack);
+        mediaExtractor.selectTrack(videoTrack);
+        return sampleTime;
+    }
+
+    public static int getTrack(MediaExtractor extractor, String willFormat) {
+        //获得信道数
+        int trackCount = extractor.getTrackCount();
+        for (int i = 0; i < trackCount; i++) {
+            MediaFormat trackFormat = extractor.getTrackFormat(i);
+            String format = trackFormat.getString(MediaFormat.KEY_MIME);
+            if (format.startsWith(willFormat)) {
+                return i;
+            }
+        }
+        return 0;
+    }
+}

+ 226 - 0
app/src/main/java/com/sheep/gamegroup/util/MediaMetadataRetrieverUtil.java

@@ -0,0 +1,226 @@
+package com.sheep.gamegroup.util;
+
+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.widget.ImageView;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.SheepApp;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import io.reactivex.Observable;
+import io.reactivex.ObservableEmitter;
+import io.reactivex.ObservableOnSubscribe;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
+/**
+ * Created by realicing on 2018/11/29.
+ * realicing@sina.com
+ * 可以获取视频帧
+ */
+public class MediaMetadataRetrieverUtil {
+    private static final String TAG = "MediaMetadataRetrieverUtil";
+    //要操作的本地视频文件
+    private String fromFile;
+    //输出路径
+    private String outDir = SheepApp.getInstance().getDir("frame", Context.MODE_PRIVATE).getAbsolutePath();
+    //视频文件的总时长,单位毫秒
+    private long duration;
+    //要截取的图片个数
+    private int size = 10;
+
+    public MediaMetadataRetrieverUtil(String fromFile, long duration) {
+        this.fromFile = fromFile;
+        this.duration = duration;
+    }
+
+    public String getFromFile() {
+        return fromFile;
+    }
+
+    public void setFromFile(String fromFile) {
+        this.fromFile = fromFile;
+    }
+
+    public String getOutDir() {
+        return outDir;
+    }
+
+    public void setOutDir(String outDir) {
+        this.outDir = outDir;
+    }
+
+    public long getDuration() {
+        return duration;
+    }
+
+    public void setDuration(long duration) {
+        this.duration = duration;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    /**
+     * 取出视频文件中的图片帧列表
+     */
+    public void initRv(final RecyclerView recyclerView) {
+        Observable.create(new ObservableOnSubscribe<List<Bitmap>>() {
+            @Override
+            public void subscribe(ObservableEmitter<List<Bitmap>> emitter) throws Exception {
+                emitter.onNext(getFrameBitmapList(fromFile, duration, size));
+            }
+        })
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new AbsObserver<List<Bitmap>>() {
+                    @Override
+                    public void onNext(final List<Bitmap> strings) {
+                        recyclerView.setLayoutManager(new GridLayoutManager(SheepApp.getInstance(), size));
+                        BaseQuickAdapter<Bitmap, BaseViewHolder> baseQuickAdapter = new BaseQuickAdapter<Bitmap, BaseViewHolder>(R.layout.item_iv_mh, strings) {
+                            @Override
+                            protected void convert(BaseViewHolder helper, Bitmap item) {
+                                ImageView imageView = helper.getView(R.id.item_iv);
+                                imageView.setImageBitmap(item);
+                            }
+                        };
+                        recyclerView.setAdapter(baseQuickAdapter);
+                    }
+                });
+
+    }
+    /**
+     * 取出视频文件中的图片帧列表
+     */
+    public void initRv2(final RecyclerView recyclerView) {
+        Observable.create(new ObservableOnSubscribe<List<String>>() {
+            @Override
+            public void subscribe(ObservableEmitter<List<String>> emitter) throws Exception {
+                emitter.onNext(getFrameFileList(fromFile, outDir, duration, size));
+            }
+        })
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .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);
+                    }
+                });
+
+    }
+
+
+    public static String getFilePath(String fromFile, String outDir, int index) {
+        return String.format(Locale.CHINA, "%s%s%s_frame_%d.png", outDir, File.separator, FileUtil.getFileNameNoExFromPath(fromFile), index);
+    }
+
+    /**
+     * 取出视频文件中的图片帧列表
+     *
+     * @param fromFile 要操作的本地视频文件
+     * @param duration 视频文件的总时长,单位毫秒
+     * @param size     需要的图片个数
+     * @return
+     */
+    public static List<Bitmap> getFrameBitmapList(String fromFile, long duration, int size) {
+        if (duration < size || size < 1) {
+            return null;
+        }
+        long per = duration * 1000L / (size - 1);
+        List<Bitmap> resultList = new ArrayList<>();
+        long time = System.currentTimeMillis();
+        MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
+        metadataRetriever.setDataSource(fromFile);
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) {
+            MediaMetadataRetriever.BitmapParams bitmapParams = new MediaMetadataRetriever.BitmapParams();
+            Bitmap.Config config = Bitmap.Config.ARGB_8888;
+            bitmapParams.setPreferredConfig(config);
+            return metadataRetriever.getFramesAtIndex(0, size, bitmapParams);
+        }
+        for (int i = 0; i < size; i++) {
+            //这里单位为微秒
+            long atTime = i + 1 == size ? (duration * 1000L) : i * per;
+            Bitmap bitmap = metadataRetriever.getFrameAtTime(atTime, MediaMetadataRetriever.OPTION_CLOSEST);
+            resultList.add(bitmap);
+        }
+        long curTime = System.currentTimeMillis();
+        LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000, (curTime - time) / 10000);
+        return resultList;
+    }
+
+    /**
+     * 取出视频文件中的图片帧列表
+     *
+     * @param fromFile 要操作的本地视频文件
+     * @param outDir   输出路径
+     * @param duration 视频文件的总时长,单位毫秒
+     * @param size     需要的图片个数
+     * @return
+     */
+    public static List<String> getFrameFileList(String fromFile, String outDir, long duration, int size) {
+        if (duration < size || size < 1) {
+            return null;
+        }
+        long per = duration * 1000L / (size - 1);
+        List<String> resultList = new ArrayList<>();
+        long time = System.currentTimeMillis();
+        MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
+        metadataRetriever.setDataSource(fromFile);
+
+        for (int i = 0; i < size; i++) {
+            //这里单位为微秒
+            long atTime = i + 1 == size ? (duration * 1000L) : i * per;
+            Bitmap bitmap = metadataRetriever.getFrameAtTime(atTime, MediaMetadataRetriever.OPTION_CLOSEST);
+
+            String path = getFilePath(fromFile, outDir, i);
+            FileOutputStream fileOutputStream = null;
+            try {
+                fileOutputStream = new FileOutputStream(path);
+                bitmap.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream);
+                resultList.add(path);
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                if (fileOutputStream != null) {
+                    try {
+                        fileOutputStream.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+            bitmap.recycle();
+        }
+        long curTime = System.currentTimeMillis();
+        LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000, (curTime - time) / 10000);
+        return resultList;
+    }
+}

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

@@ -476,7 +476,7 @@ public class TestUtil {
                                 G.showToast(md5);
                                 G.showToast(md5);
                                 break;
                                 break;
                             case "空间不足提示框":
                             case "空间不足提示框":
-                                DialogStorageLow.showDialog(activity);
+                                DialogStorageLow.showDialog(null);
                                 break;
                                 break;
                             case "显示已经安装应用列表":
                             case "显示已经安装应用列表":
                                 showHasInstallApkList(activity);
                                 showHasInstallApkList(activity);

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

@@ -239,7 +239,7 @@ public class TimeUtil {
         }
         }
     }
     }
 
 
-    public static String getDurationText(int duration) {
+    public static String getDurationText(long duration) {
         if(duration > 3600)
         if(duration > 3600)
             return String.format(Locale.CHINA, "%d:%d:%d", duration / 3600, duration / 60 % 60, duration % 60);
             return String.format(Locale.CHINA, "%d:%d:%d", duration / 3600, duration / 60 % 60, duration % 60);
         else if(duration > 60)
         else if(duration > 60)

+ 60 - 12
app/src/main/java/com/sheep/gamegroup/util/ViewUtil.java

@@ -18,12 +18,10 @@ import android.media.MediaPlayer;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Build;
 import android.provider.MediaStore;
 import android.provider.MediaStore;
-import android.support.annotation.IntegerRes;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.LayoutRes;
 import android.support.annotation.StringRes;
 import android.support.annotation.StringRes;
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentActivity;
 import android.support.v7.app.AlertDialog;
 import android.support.v7.app.AlertDialog;
-import android.support.v7.widget.AppCompatCheckedTextView;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView;
@@ -70,11 +68,13 @@ import com.sheep.gamegroup.model.entity.Container;
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.DialogConfig;
 import com.sheep.gamegroup.model.entity.GameAccountEntity;
 import com.sheep.gamegroup.model.entity.GameAccountEntity;
 import com.sheep.gamegroup.model.entity.GiftBagApp;
 import com.sheep.gamegroup.model.entity.GiftBagApp;
+import com.sheep.gamegroup.model.entity.Lp;
 import com.sheep.gamegroup.model.entity.PayEntity;
 import com.sheep.gamegroup.model.entity.PayEntity;
 import com.sheep.gamegroup.model.entity.RobTask;
 import com.sheep.gamegroup.model.entity.RobTask;
 import com.sheep.gamegroup.model.entity.TaskEty;
 import com.sheep.gamegroup.model.entity.TaskEty;
 import com.sheep.gamegroup.util.glide.RoundedCornersTransformation;
 import com.sheep.gamegroup.util.glide.RoundedCornersTransformation;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
+import com.sheep.gamegroup.util.viewHelper.LayoutParamsUtil;
 import com.sheep.gamegroup.view.activity.ActMain;
 import com.sheep.gamegroup.view.activity.ActMain;
 import com.sheep.gamegroup.view.activity.PersonalInfoAct;
 import com.sheep.gamegroup.view.activity.PersonalInfoAct;
 import com.sheep.gamegroup.view.activity.SplashAct;
 import com.sheep.gamegroup.view.activity.SplashAct;
@@ -111,7 +111,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
-import java.util.Observable;
 import java.util.Random;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 
 
@@ -280,24 +279,26 @@ public class ViewUtil {
     }
     }
 
 
     public static void dismiss(DialogProgress dialogProgress, int delay) {
     public static void dismiss(DialogProgress dialogProgress, int delay) {
-        if(dialogProgress != null ){
+        if (dialogProgress != null) {
             dismiss(dialogProgress.getAlertDialog(), delay);
             dismiss(dialogProgress.getAlertDialog(), delay);
         }
         }
     }
     }
+
     public static void dismiss(DialogLoading dialogLoading, int delay) {
     public static void dismiss(DialogLoading dialogLoading, int delay) {
-        if(dialogLoading != null ){
+        if (dialogLoading != null) {
             dismiss(dialogLoading.getAlertDialog(), delay);
             dismiss(dialogLoading.getAlertDialog(), delay);
         }
         }
     }
     }
+
     public static void dismiss(final AlertDialog dialog, int delay) {
     public static void dismiss(final AlertDialog dialog, int delay) {
-        if(dialog != null ){
-            if(delay > 0){
+        if (dialog != null) {
+            if (delay > 0) {
                 delay(new AbsObserver<Integer>() {
                 delay(new AbsObserver<Integer>() {
                     @Override
                     @Override
                     public void onNext(Integer integer) {
                     public void onNext(Integer integer) {
                         try {
                         try {
                             dialog.dismiss();
                             dialog.dismiss();
-                        } catch (Exception ignore){
+                        } catch (Exception ignore) {
 
 
                         }
                         }
                     }
                     }
@@ -307,6 +308,7 @@ public class ViewUtil {
             }
             }
         }
         }
     }
     }
+
     public static void delay(Observer<Integer> observer, int delay) {
     public static void delay(Observer<Integer> observer, int delay) {
         io.reactivex.Observable.just(1)
         io.reactivex.Observable.just(1)
                 .delay(delay, TimeUnit.SECONDS)
                 .delay(delay, TimeUnit.SECONDS)
@@ -316,7 +318,7 @@ public class ViewUtil {
     }
     }
 
 
     public static void setChecked(Checkable view, boolean checked) {
     public static void setChecked(Checkable view, boolean checked) {
-        if(view != null)
+        if (view != null)
             view.setChecked(checked);
             view.setChecked(checked);
     }
     }
 
 
@@ -1589,9 +1591,32 @@ public class ViewUtil {
             }
             }
         }
         }
     }
     }
+
+    public static void setViewWH(ImageView imageView, String pictures, int width) {
+        if (imageView != null) {
+            if (TextUtils.isEmpty(pictures)) {
+                imageView.setImageResource(R.mipmap.icon);
+            } else {
+                if (pictures.contains(";")) {
+                    pictures = pictures.split(";")[0];
+                }
+                Uri uri = Uri.parse(pictures);
+                int w = NumberFormatUtils.parseInteger(uri.getQueryParameter("w"));
+                int h = NumberFormatUtils.parseInteger(uri.getQueryParameter("h"));
+                if (w > 0 && h > 0) {
+                    LayoutParamsUtil.resetLayoutParams(imageView, new Lp().setWidth(width).setHeight((int) (width * h * 1.0f / w)));
+                }
+            }
+        }
+    }
+
+    public static void setViewWH(View view, int width, float radio) {
+        LayoutParamsUtil.resetLayoutParams(view, new Lp().setWidth(width).setHeight((int) (width * radio)));
+    }
+
     public static void setImagePath(ImageView imageView, String paths) {
     public static void setImagePath(ImageView imageView, String paths) {
-        if (imageView != null){
-            if(TextUtils.isEmpty(paths)) {
+        if (imageView != null) {
+            if (TextUtils.isEmpty(paths)) {
                 imageView.setImageResource(R.mipmap.icon);
                 imageView.setImageResource(R.mipmap.icon);
             } else {
             } else {
                 if (paths.contains(";")) {
                 if (paths.contains(";")) {
@@ -1602,6 +1627,19 @@ public class ViewUtil {
         }
         }
     }
     }
 
 
+    public static void setImagePath(ImageView imageView, String paths, int radio) {
+        if (imageView != null) {
+            if (TextUtils.isEmpty(paths)) {
+                imageView.setImageResource(R.mipmap.icon);
+            } else {
+                if (paths.contains(";")) {
+                    paths = paths.split(";")[0];
+                }
+                Glide.with(SheepApp.getInstance()).load(new File(paths)).apply(new RequestOptions().transform(new RoundedCornersTransformation(radio, 0))).into(imageView);
+            }
+        }
+    }
+
     public static void setImageLoading(ImageView imageView, String pictures) {
     public static void setImageLoading(ImageView imageView, String pictures) {
         if (imageView != null) {
         if (imageView != null) {
             if (TextUtils.isEmpty(pictures)) {
             if (TextUtils.isEmpty(pictures)) {
@@ -1671,12 +1709,19 @@ public class ViewUtil {
             textView.setText(TextUtils.isEmpty(msg) ? "" : msg);
             textView.setText(TextUtils.isEmpty(msg) ? "" : msg);
         }
         }
     }
     }
-    public static void setText(TextView textView, @StringRes int stringId, Object...objects) {
+
+    public static void setText(TextView textView, @StringRes int stringId, Object... objects) {
         if (textView != null) {
         if (textView != null) {
             textView.setText(SheepApp.getInstance().getString(stringId, objects));
             textView.setText(SheepApp.getInstance().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 setText(TextView textView, IContentTypeContainer<Integer, String> contentTypeContainer, int maxWidth) {
     public static void setText(TextView textView, IContentTypeContainer<Integer, String> contentTypeContainer, int maxWidth) {
         switch (contentTypeContainer.getContentType()) {
         switch (contentTypeContainer.getContentType()) {
             case StringUtils.CONTENT_TYPE_FONT:
             case StringUtils.CONTENT_TYPE_FONT:
@@ -1798,11 +1843,13 @@ public class ViewUtil {
             view.setVisibility(isVisible ? View.VISIBLE : View.GONE);
             view.setVisibility(isVisible ? View.VISIBLE : View.GONE);
         }
         }
     }
     }
+
     public static void toggleVisibility(View view) {
     public static void toggleVisibility(View view) {
         if (view != null) {
         if (view != null) {
             view.setVisibility(isVisible(view) ? View.GONE : View.VISIBLE);
             view.setVisibility(isVisible(view) ? View.GONE : View.VISIBLE);
         }
         }
     }
     }
+
     public static boolean isVisible(View view) {
     public static boolean isVisible(View view) {
         return view != null && view.getVisibility() == View.VISIBLE;
         return view != null && view.getVisibility() == View.VISIBLE;
     }
     }
@@ -1812,6 +1859,7 @@ public class ViewUtil {
             view.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
             view.setVisibility(isVisible ? View.VISIBLE : View.INVISIBLE);
         }
         }
     }
     }
+
     public static void toggleVisibility2(View view) {
     public static void toggleVisibility2(View view) {
         if (view != null) {
         if (view != null) {
             view.setVisibility(isVisible(view) ? View.INVISIBLE : View.VISIBLE);
             view.setVisibility(isVisible(view) ? View.INVISIBLE : View.VISIBLE);

+ 510 - 0
app/src/main/java/com/sheep/gamegroup/view/activity/ActCutVideo.java

@@ -0,0 +1,510 @@
+package com.sheep.gamegroup.view.activity;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.media.AudioManager;
+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.text.TextUtils;
+import android.view.GestureDetector;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.TextView;
+import android.widget.VideoView;
+
+import com.kfzs.duanduan.utils.NumberFormatUtils;
+import com.kfzs.duanduan.utils.StatusBarUtils;
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.gamegroup.absBase.BaseContainerActivity;
+import com.sheep.gamegroup.model.entity.DiscoveryTopic;
+import com.sheep.gamegroup.model.entity.Video;
+import com.sheep.gamegroup.util.DataUtil;
+import com.sheep.gamegroup.util.Jump2View;
+import com.sheep.gamegroup.util.KeyEventUtil;
+import com.sheep.gamegroup.util.LogUtil;
+import com.sheep.gamegroup.util.MediaHandleUtil;
+import com.sheep.gamegroup.util.TestUtil;
+import com.sheep.gamegroup.util.ViewUtil;
+import com.sheep.gamegroup.view.customview.VideoFramesView;
+import com.sheep.gamegroup.view.fragment.FgtDiscoveryTopic;
+import com.sheep.jiuyan.samllsheep.R;
+import com.sheep.jiuyan.samllsheep.utils.G;
+
+import org.greenrobot.eventbus.Subscribe;
+
+import java.util.Locale;
+
+import butterknife.BindView;
+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, View.OnLayoutChangeListener {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        StatusBarUtils.setTranslucent(this);
+        super.onCreate(savedInstanceState);
+    }
+
+    @BindView(R.id.videoView)
+    VideoView videoView;
+    @BindView(R.id.video_loading)
+    View video_loading;
+    @BindView(R.id.videoFramesView)
+    VideoFramesView videoFramesView;
+    @BindView(R.id.edit_video_time_tv)
+    TextView edit_video_time_tv;
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.act_edit_video;
+    }
+
+    public static final long MAX_VIDEO_DURATION = 15_000L;//视频最大时长,超过需要剪切
+    private Video data;
+
+    @Override
+    public void initView() {
+        super.initView();
+        initVolume();
+        data = DataUtil.getObject(getIntent(), Video.class);
+        Uri uri = Uri.parse(data.getFilePath());
+        videoView.setOnInfoListener(this);
+        videoView.setOnPreparedListener(this);
+        videoView.setOnErrorListener(this);
+        videoView.setOnCompletionListener(this);
+        videoView.addOnLayoutChangeListener(this);
+//        videoView.setMediaController(new MediaController(this));
+        videoView.setVideoURI(uri);
+        videoFramesView.initVideo(data).setMaxDuration(MAX_VIDEO_DURATION).showVideoList().setOnTimeChangeListener(new Action1<Float>() {
+            @Override
+            public void call(Float duration) {
+                if(duration == null)
+                    return;
+                if(ViewUtil.isVisible(videoFramesView))
+                    checkDuration(duration.longValue());
+                ViewUtil.setText(edit_video_time_tv, R.string.has_choose_x_second, NumberFormatUtils.retainMost1(duration / 1000.0f));
+                if (TestUtil.isDev()) {
+                    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
+        ViewUtil.setVisibility2(edit_video_time_tv, false);
+        ViewUtil.setVisibility2(videoFramesView, false);
+    }
+
+    //检查有没有设置剪切视频的时长
+    private void checkDuration(long duration) {
+        if ((data.getDuration() - duration) >= 1000) {
+            ViewUtil.setText(edit_video_sure_tv, BTN_TEXT_FINISH);
+        } else {
+            ViewUtil.setText(edit_video_sure_tv, BTN_TEXT_CUT);
+        }
+    }
+
+    @Override
+    protected Fragment initFragment() {
+        return new FgtDiscoveryTopic();
+    }
+
+    @SuppressLint("ClickableViewAccessibility")
+    @Override
+    public void initListener() {
+        mGestureDetector = new GestureDetector(getApplicationContext(), mGestureListener);
+        View.OnTouchListener listener = new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                return onTouchEvent(event);
+            }
+        };
+        videoView.setOnTouchListener(listener);
+    }
+
+    private GestureDetector mGestureDetector;
+
+    //播放或者暂停
+    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
+    public boolean onTouchEvent(MotionEvent event) {
+        return mGestureDetector.onTouchEvent(event);
+    }
+
+    @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();
+        mAudioManager = null;
+    }
+
+    //    //滑动方向
+//    private int direction = 0;
+//    //左右滑动
+//    public static final int DIRECTION_LEFT_RIGHT = 1;
+//    //上下滑动
+//    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;
+            return super.onDown(e);
+        }
+
+        @Override
+        public void onLongPress(MotionEvent e) {
+            LogUtil.println("mGestureListener", "onLongPress");
+            super.onLongPress(e);
+        }
+
+        @Override
+        public boolean onSingleTapConfirmed(MotionEvent e) {
+            LogUtil.println("mGestureListener", "onSingleTapConfirmed");
+//            if(isPlaying)
+//                isPauseByUser = true;
+//            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 = ActCutVideo.this.windowWidth;
+            int windowHeight = ActCutVideo.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);
+        }
+
+
+//        @Override
+//        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);
+//        }
+//
+//        @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");
+//                //音量增益减
+//            } else if (event2.getX() - event1.getX() > FLING_MIN_DISTANCE
+//                    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
+//                // Fling right
+//                LogUtil.println("mGestureListener", "Fling rigth");
+//                //音量增益加
+//            } 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;
+//        }
+    };
+    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);
+        }
+
+        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);
+        }
+        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);
+        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");
+    }
+
+    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;
+    }
+
+
+    @BindView(R.id.edit_video_topic_tv)
+    TextView edit_video_topic_tv;
+    @BindView(R.id.edit_video_sure_tv)
+    TextView edit_video_sure_tv;
+    @BindView(R.id.frame_container)
+    View frame_container;
+
+    @Override
+    protected boolean needRegisterEventBus() {
+        return true;
+    }
+
+    @Subscribe
+    public void onEventMainThread(DiscoveryTopic result) {
+        ViewUtil.setText(edit_video_topic_tv, "#%s#", result.getTopic());
+        data.setTopicId(result.getId());
+    }
+
+    //点击话题进行切换
+    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:
+                finishCut();
+                break;
+            case BTN_TEXT_FINISH:
+                goEditVideo();
+                break;
+        }
+    }
+
+    private void goEditVideo() {//完成并跳转编辑视频界面
+        Jump2View.getInstance().goActEditVideo(data);
+        finish();
+    }
+
+    private void finishCut() {//其次完成编辑
+        G.showToast("开始剪切");
+        new MediaHandleUtil(data.getFilePath(), videoFramesView.getStartPoint() * 1000, videoFramesView.getLineDuration() * 1000)
+                .tryCutVideo(new AbsObserver<Video>() {
+                    @Override
+                    public void onNext(Video video) {
+                        data.setFilePath(video.getFilePath());
+                        data.setWidth(video.getWidth());
+                        data.setHeight(video.getHeight());
+                        data.setDuration(video.getDuration());
+                        G.showToast("完成剪切");
+                        goEditVideo();
+                    }
+
+                    @Override
+                    public void onError(Throwable e) {
+                        G.showToast(e.getMessage());
+                    }
+                });
+    }
+
+    private void showCut() {//首先隐藏话题列表
+        ViewUtil.setVisibility(frame_container, false);
+        ViewUtil.setVisibility2(edit_video_time_tv, true);
+        ViewUtil.setVisibility2(videoFramesView, true);
+        checkDuration(videoFramesView.getLineDuration());
+    }
+}

+ 38 - 0
app/src/main/java/com/sheep/gamegroup/view/activity/ActEditVideo.java

@@ -0,0 +1,38 @@
+package com.sheep.gamegroup.view.activity;
+
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import com.kfzs.duanduan.utils.StatusBarUtils;
+import com.sheep.gamegroup.absBase.BaseActivity;
+import com.sheep.gamegroup.model.entity.Video;
+import com.sheep.gamegroup.util.DataUtil;
+import com.sheep.jiuyan.samllsheep.R;
+
+/**
+ * Created by realicing on 2018/11/9.
+ * realicing@sina.com
+ * 编辑视频
+ */
+public class ActEditVideo extends BaseActivity {
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        StatusBarUtils.setTranslucent(this);
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected int getLayoutId() {
+        return R.layout.act_cut_video;
+    }
+
+    private Video data;
+
+    @Override
+    public void initView() {
+        data = DataUtil.getObject(getIntent(), Video.class);
+        Uri uri = Uri.parse(data.getFilePath());
+    }
+}

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

@@ -399,7 +399,7 @@ public class ActMain extends BaseActYmPermissionCheck  {
     public void onEventMainThread(BigEvent event) {
     public void onEventMainThread(BigEvent event) {
         switch (event.getEventTypes()) {
         switch (event.getEventTypes()) {
             case STORAGE_LOW:
             case STORAGE_LOW:
-                DialogStorageLow.showDialog(this);
+                DialogStorageLow.showDialog(null);
                 break;
                 break;
         }
         }
         if (progressView != null && event.getData() instanceof DownLoadInfo) {
         if (progressView != null && event.getData() instanceof DownLoadInfo) {

+ 2 - 1
app/src/main/java/com/sheep/gamegroup/view/activity/ActPlayVideo.java

@@ -130,8 +130,9 @@ public class ActPlayVideo extends BaseActivity implements MediaPlayer.OnInfoList
 
 
     @Override
     @Override
     protected void onDestroy() {
     protected void onDestroy() {
-        super.onDestroy();
         destroy();
         destroy();
+        super.onDestroy();
+        mAudioManager = null;
     }
     }
 
 
 //    //滑动方向
 //    //滑动方向

+ 7 - 1
app/src/main/java/com/sheep/gamegroup/view/activity/ActPlayVideoArticle.java

@@ -21,9 +21,11 @@ import android.widget.VideoView;
 
 
 import com.kfzs.duanduan.utils.StatusBarUtils;
 import com.kfzs.duanduan.utils.StatusBarUtils;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.BaseActivity;
+import com.sheep.gamegroup.absBase.IRefresh;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.DiscoveryVideo;
 import com.sheep.gamegroup.model.entity.DiscoveryVideo;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
+import com.sheep.gamegroup.util.ActionUtil;
 import com.sheep.gamegroup.util.ApiUtil;
 import com.sheep.gamegroup.util.ApiUtil;
 import com.sheep.gamegroup.util.DataUtil;
 import com.sheep.gamegroup.util.DataUtil;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.Jump2View;
@@ -32,6 +34,7 @@ import com.sheep.gamegroup.util.TestUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.util.share.CommonUMShareListener;
 import com.sheep.gamegroup.util.share.CommonUMShareListener;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
 import com.sheep.gamegroup.util.share.ShareLinkConfig;
+import com.sheep.gamegroup.view.fragment.FgtArticleVideo;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.G;
@@ -262,6 +265,8 @@ public class ActPlayVideoArticle extends BaseActivity implements MediaPlayer.OnI
                             }
                             }
                             loadVideoData(newVideo);
                             loadVideoData(newVideo);
                         }
                         }
+                        //回去视频列表后需要刷新界面
+                        ActionUtil.getInstance().addNextAction(FgtArticleVideo.class.getSimpleName(), IRefresh.class.getSimpleName());
                     }
                     }
 
 
                     @Override
                     @Override
@@ -334,8 +339,9 @@ public class ActPlayVideoArticle extends BaseActivity implements MediaPlayer.OnI
 
 
     @Override
     @Override
     protected void onDestroy() {
     protected void onDestroy() {
-        super.onDestroy();
         destroy();
         destroy();
+        super.onDestroy();
+        mAudioManager = null;
     }
     }
 
 
     //    //滑动方向
     //    //滑动方向

+ 45 - 44
app/src/main/java/com/sheep/gamegroup/view/activity/ActPublishArticle.java

@@ -14,23 +14,28 @@ import com.chad.library.adapter.base.BaseViewHolder;
 import com.qiniu.android.http.ResponseInfo;
 import com.qiniu.android.http.ResponseInfo;
 import com.qiniu.android.storage.UpCompletionHandler;
 import com.qiniu.android.storage.UpCompletionHandler;
 import com.qiniu.android.storage.UpProgressHandler;
 import com.qiniu.android.storage.UpProgressHandler;
+import com.sheep.gamegroup.absBase.AbsObserver;
 import com.sheep.gamegroup.absBase.BaseActivity;
 import com.sheep.gamegroup.absBase.BaseActivity;
+import com.sheep.gamegroup.absBase.IRefresh;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.CreateUserVideoReq;
 import com.sheep.gamegroup.model.entity.CreateUserVideoReq;
 import com.sheep.gamegroup.model.entity.InputAndUrlList;
 import com.sheep.gamegroup.model.entity.InputAndUrlList;
+import com.sheep.gamegroup.model.entity.Video;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
 import com.sheep.gamegroup.model.util.SheepSubscriber;
+import com.sheep.gamegroup.util.ActionUtil;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.Jump2View;
 import com.sheep.gamegroup.util.ListUtil;
 import com.sheep.gamegroup.util.ListUtil;
 import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.gamegroup.util.LogUtil;
 import com.sheep.gamegroup.util.QiNiuUploadUtil;
 import com.sheep.gamegroup.util.QiNiuUploadUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.util.ViewUtil;
-import com.sheep.gamegroup.view.dialog.DialogLoading;
 import com.sheep.gamegroup.view.dialog.DialogProgress;
 import com.sheep.gamegroup.view.dialog.DialogProgress;
+import com.sheep.gamegroup.view.fragment.FgtArticleVideo;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.G;
 import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
 import com.sheep.jiuyan.samllsheep.utils.TitleBarUtils;
 
 
+import org.greenrobot.eventbus.Subscribe;
 import org.json.JSONException;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONObject;
 
 
@@ -38,13 +43,7 @@ import java.io.File;
 import java.util.Locale;
 import java.util.Locale;
 
 
 import butterknife.BindView;
 import butterknife.BindView;
-import cn.finalteam.rxgalleryfinal.RxGalleryFinalApi;
-import cn.finalteam.rxgalleryfinal.bean.ImageCropBean;
-import cn.finalteam.rxgalleryfinal.bean.MediaBean;
-import cn.finalteam.rxgalleryfinal.rxbus.RxBusResultDisposable;
-import cn.finalteam.rxgalleryfinal.rxbus.event.ImageRadioResultEvent;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.functions.Function;
 import io.reactivex.schedulers.Schedulers;
 import io.reactivex.schedulers.Schedulers;
 
 
 import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
 import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
@@ -103,7 +102,7 @@ public class ActPublishArticle extends BaseActivity {
                     helper.itemView.setOnClickListener(new View.OnClickListener() {
                     helper.itemView.setOnClickListener(new View.OnClickListener() {
                         @Override
                         @Override
                         public void onClick(View view) {
                         public void onClick(View view) {
-                            Jump2View.getInstance().goActPlayVideo(item, false);
+                            addVideo();
                         }
                         }
                     });
                     });
                 }
                 }
@@ -123,33 +122,9 @@ public class ActPublishArticle extends BaseActivity {
     }
     }
 
 
     private void addVideo() {
     private void addVideo() {
-        RxGalleryFinalApi
-                .getInstance(ActPublishArticle.this)
-                .setFilter(new Function<MediaBean, Boolean>() {
-                    @Override
-                    public Boolean apply(MediaBean mediaBean) throws Exception {
-                        boolean result = mediaBean.getDuration() > 15_000L;
-                        if (result) {
-                            G.showToast(R.string.need_picker_video_dur_15);
-                        }
-                        return result;
-                    }
-                })
-                .setType(RxGalleryFinalApi.SelectRXType.TYPE_VIDEO, RxGalleryFinalApi.SelectRXType.TYPE_SELECT_RADIO)
-                .setVDRadioResultEvent(new RxBusResultDisposable<ImageRadioResultEvent>() {
-                    @Override
-                    protected void onEvent(ImageRadioResultEvent imageRadioResultEvent) throws Exception {
-                        ListUtil.removeNull(inputAndUrlList.getList());
-                        inputAndUrlList.getList().add(imageRadioResultEvent.getResult().getOriginalPath());
-                        ViewUtil.notifyDataSetChanged(recyclerView);
-                        imageCropBean = imageRadioResultEvent.getResult();
-
-                    }
-                })
-                .open();
+        Jump2View.getInstance().gotoActMediaChoose(MEDIA_TYPE_NONE);
     }
     }
 
 
-    private ImageCropBean imageCropBean;
     private int uploadType = UPLOAD_TYPE_NONE;
     private int uploadType = UPLOAD_TYPE_NONE;
 
 
     //点击确定按钮
     //点击确定按钮
@@ -163,13 +138,14 @@ public class ActPublishArticle extends BaseActivity {
 //            G.showToast(R.string.nedd_picker_img);
 //            G.showToast(R.string.nedd_picker_img);
 //            return;
 //            return;
 //        }
 //        }
-        if (imageCropBean == null) {
+        if (isErrorVideo()) {
             G.showToast(R.string.need_picker_video);
             G.showToast(R.string.need_picker_video);
             return;
             return;
         }
         }
         jsonObject.put("resource_type", CreateUserVideoReq.TYPE_VIDEO);
         jsonObject.put("resource_type", CreateUserVideoReq.TYPE_VIDEO);
         jsonObject.put("title", input);
         jsonObject.put("title", input);
-        jsonObject.put("duration", imageCropBean.getDuration() / 1000);
+        jsonObject.put("duration", video.getDuration() / 1000);
+        jsonObject.put("topic_id", video.getTopicId());
         inputAndUrlList.setInput(input);
         inputAndUrlList.setInput(input);
         switch (uploadType) {
         switch (uploadType) {
             case UPLOAD_TYPE_NONE:
             case UPLOAD_TYPE_NONE:
@@ -188,14 +164,19 @@ public class ActPublishArticle extends BaseActivity {
         }
         }
     }
     }
 
 
+    //
+    private boolean isErrorVideo() {
+        return video == null || video.getFilePath() == null || !new File(video.getFilePath()).exists();
+    }
+
     private void uploadFile() {
     private void uploadFile() {
         final DialogProgress dialogProgress = DialogProgress.showDialog(this);
         final DialogProgress dialogProgress = DialogProgress.showDialog(this);
         uploadType = UPLOAD_TYPE_START;
         uploadType = UPLOAD_TYPE_START;
-        QiNiuUploadUtil.getInstance().uploadFile(imageCropBean.getOriginalPath()/*, QiNiuUploadUtil.TAG_VIDEO*/, new UpCompletionHandler() {
+        QiNiuUploadUtil.getInstance().uploadFile(video.getFilePath()/*, QiNiuUploadUtil.TAG_VIDEO*/, new UpCompletionHandler() {
             @Override
             @Override
             public void complete(String key, ResponseInfo info, JSONObject response) {
             public void complete(String key, ResponseInfo info, JSONObject response) {
                 LogUtil.println("qiniu", key, info, response);
                 LogUtil.println("qiniu", key, info, response);
-                if(info == null){
+                if (info == null) {
                     ViewUtil.setText(dialogProgress.getTextView(), "上传失败");
                     ViewUtil.setText(dialogProgress.getTextView(), "上传失败");
                     ViewUtil.dismiss(dialogProgress, 1);
                     ViewUtil.dismiss(dialogProgress, 1);
                     uploadType = UPLOAD_TYPE_FAIL;
                     uploadType = UPLOAD_TYPE_FAIL;
@@ -212,7 +193,7 @@ public class ActPublishArticle extends BaseActivity {
                         e.printStackTrace();
                         e.printStackTrace();
                     }
                     }
                     jsonObject.put("resource", url);
                     jsonObject.put("resource", url);
-                    jsonObject.put("cover", url + "?vframe/jpg/offset/0");
+                    jsonObject.put("cover", String.format(Locale.CHINA, "%s?vframe/jpg/offset/0&w=%d&h=%d", url, video.getWidth(), video.getHeight()));
                     publishArticle(dialogProgress);
                     publishArticle(dialogProgress);
                 } else {
                 } else {
                     ViewUtil.setText(dialogProgress.getTextView(), "上传失败");
                     ViewUtil.setText(dialogProgress.getTextView(), "上传失败");
@@ -222,12 +203,12 @@ public class ActPublishArticle extends BaseActivity {
                 }
                 }
                 LogUtil.println("qiniu", key + ",\r\n " + info + ",\r\n " + response);
                 LogUtil.println("qiniu", key + ",\r\n " + info + ",\r\n " + response);
             }
             }
-        },new UpProgressHandler(){
-                    public void progress(String key, double percent){
-                        LogUtil.println("qiniu", key + ": " + percent);
-                        ViewUtil.setText(dialogProgress.getTextView(), String.format(Locale.CHINA, "%d%%", (int)(percent * 100)));
-                    }
-                });
+        }, new UpProgressHandler() {
+            public void progress(String key, double percent) {
+                LogUtil.println("qiniu", key + ": " + percent);
+                ViewUtil.setText(dialogProgress.getTextView(), String.format(Locale.CHINA, "%d%%", (int) (percent * 100)));
+            }
+        });
     }
     }
 
 
     private com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
     private com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
@@ -241,6 +222,13 @@ public class ActPublishArticle extends BaseActivity {
                     public void onNext(BaseMessage baseMessage) {
                     public void onNext(BaseMessage baseMessage) {
                         ViewUtil.setText(dialogProgress.getTextView(), "发布成功");
                         ViewUtil.setText(dialogProgress.getTextView(), "发布成功");
                         ViewUtil.dismiss(dialogProgress, 1);
                         ViewUtil.dismiss(dialogProgress, 1);
+                        ViewUtil.delay(new AbsObserver<Integer>() {
+                            @Override
+                            public void onNext(Integer integer) {
+                                ActionUtil.getInstance().addNextAction(FgtArticleVideo.class.getSimpleName(), IRefresh.class.getSimpleName());
+                                ActPublishArticle.this.finish();
+                            }
+                        },1);
                     }
                     }
 
 
                     @Override
                     @Override
@@ -254,4 +242,17 @@ public class ActPublishArticle extends BaseActivity {
     @IntDef({MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_NONE})
     @IntDef({MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_NONE})
     public @interface Type {
     public @interface Type {
     }
     }
+
+    @Override
+    protected boolean needRegisterEventBus() {
+        return true;
+    }
+    private Video video;
+    @Subscribe
+    public void onEventMainThread(Video data) {
+        this.video = data;
+        ListUtil.removeNull(inputAndUrlList.getList());
+        inputAndUrlList.getList().add(video.getFilePath());
+        ViewUtil.notifyDataSetChanged(recyclerView);
+    }
 }
 }

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

@@ -4,6 +4,8 @@ import android.view.View;
 import android.widget.ImageView;
 import android.widget.ImageView;
 import android.widget.TextView;
 import android.widget.TextView;
 
 
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
 import com.kfzs.appstore.utils.adapter.recyclerview.RecyclerViewAdapter;
 import com.kfzs.appstore.utils.adapter.recyclerview.RecyclerViewAdapter;
 import com.kfzs.appstore.utils.adapter.recyclerview.ViewHolder;
 import com.kfzs.appstore.utils.adapter.recyclerview.ViewHolder;
 import com.kfzs.duanduan.utils.NumberFormatUtils;
 import com.kfzs.duanduan.utils.NumberFormatUtils;
@@ -13,6 +15,7 @@ import com.sheep.gamegroup.util.TimeUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.gamegroup.util.ViewUtil;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.R;
 import com.sheep.jiuyan.samllsheep.SheepApp;
 import com.sheep.jiuyan.samllsheep.SheepApp;
+import com.sheep.jiuyan.samllsheep.utils.G;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
@@ -27,12 +30,15 @@ public class AdpVideo extends RecyclerViewAdapter<DiscoveryVideo> {
         super(SheepApp.getInstance(), layoutId, datas);
         super(SheepApp.getInstance(), layoutId, datas);
     }
     }
 
 
+    private int width = (G.WIDTH - G.getRealPix(48)) / 2;
+
     @Override
     @Override
     public void convert(ViewHolder viewHolder, final DiscoveryVideo item, int position) {
     public void convert(ViewHolder viewHolder, final DiscoveryVideo item, int position) {
         ImageView item_video_cover = viewHolder.itemView.findViewById(R.id.item_video_cover);
         ImageView item_video_cover = viewHolder.itemView.findViewById(R.id.item_video_cover);
         TextView item_video_play_no_tv = viewHolder.itemView.findViewById(R.id.item_video_play_no_tv);
         TextView item_video_play_no_tv = viewHolder.itemView.findViewById(R.id.item_video_play_no_tv);
         TextView item_video_time_tv = viewHolder.itemView.findViewById(R.id.item_video_time_tv);
         TextView item_video_time_tv = viewHolder.itemView.findViewById(R.id.item_video_time_tv);
-        ViewUtil.setImage(item_video_cover, item.getCover());
+        ViewUtil.setViewWH(item_video_cover, item.getCover(), width);
+        ViewUtil.setImage(item_video_cover, item.getCover(), G.getRealPix(5));
         ViewUtil.setVisibility(item_video_play_no_tv, item.getPlay() > 0);
         ViewUtil.setVisibility(item_video_play_no_tv, item.getPlay() > 0);
         ViewUtil.setText(item_video_play_no_tv, String.format(Locale.CHINA, "%s次播放", NumberFormatUtils.getText(item.getPlay())));
         ViewUtil.setText(item_video_play_no_tv, String.format(Locale.CHINA, "%s次播放", NumberFormatUtils.getText(item.getPlay())));
         ViewUtil.setText(item_video_time_tv, TimeUtil.getDurationText(item.getDuration()));
         ViewUtil.setText(item_video_time_tv, TimeUtil.getDurationText(item.getDuration()));

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

@@ -0,0 +1,268 @@
+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();
+                    }
+                }
+            }
+        }
+    }
+}

+ 8 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment.java

@@ -98,7 +98,7 @@ public abstract class BaseListFragment<T> extends BaseFragment implements IRefre
     public void loadMoreData() {
     public void loadMoreData() {
         if (!loadMore) {
         if (!loadMore) {
             loadMore = true;
             loadMore = true;
-            if (ListUtil.size(list) >= per_page * page) {
+            if (hasMore()) {
                 page += 1;
                 page += 1;
                 initNetAndData();
                 initNetAndData();
             } else {
             } else {
@@ -109,6 +109,13 @@ public abstract class BaseListFragment<T> extends BaseFragment implements IRefre
             view_list.loadMoreComplete();
             view_list.loadMoreComplete();
         }
         }
     }
     }
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
 
 
     public void setNoMore(boolean noMore) {
     public void setNoMore(boolean noMore) {
         this.noMore = noMore;
         this.noMore = noMore;

+ 18 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment2.java

@@ -3,6 +3,7 @@ package com.sheep.gamegroup.view.fragment;
 import android.app.Activity;
 import android.app.Activity;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
 import android.view.View;
 import android.view.View;
 
 
 import com.jcodecraeer.xrecyclerview.XRecyclerView;
 import com.jcodecraeer.xrecyclerview.XRecyclerView;
@@ -108,7 +109,7 @@ public abstract class BaseListFragment2<T> extends BaseFragment implements IRefr
     public void loadMoreData() {
     public void loadMoreData() {
         if (!loadMore) {
         if (!loadMore) {
             loadMore = true;
             loadMore = true;
-            if (ListUtil.size(list) >= per_page * page) {
+            if (hasMore()) {
                 page += 1;
                 page += 1;
                 initData();
                 initData();
             } else {
             } else {
@@ -119,6 +120,14 @@ public abstract class BaseListFragment2<T> extends BaseFragment implements IRefr
             view_list.loadMoreComplete();
             view_list.loadMoreComplete();
         }
         }
     }
     }
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
+
 
 
     public void setNoMore(boolean noMore) {
     public void setNoMore(boolean noMore) {
         this.noMore = noMore;
         this.noMore = noMore;
@@ -270,4 +279,12 @@ public abstract class BaseListFragment2<T> extends BaseFragment implements IRefr
     public void notifyData(){
     public void notifyData(){
 
 
     }
     }
+    @Override
+    public void doNextAction(Object action) {
+        if(action instanceof String) {
+            if(TextUtils.equals((String) action, IRefresh.class.getSimpleName())){
+                refreshData();
+            }
+        }
+    }
 }
 }

+ 8 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment3.java

@@ -88,7 +88,7 @@ public abstract class BaseListFragment3<T> extends BaseRefreshLoadMoreFragment{
 
 
     //加载更多数据
     //加载更多数据
     public void loadMoreData() {
     public void loadMoreData() {
-        if (ListUtil.size(list) >= per_page * page) {
+        if (hasMore()) {
             page += 1;
             page += 1;
             initData();
             initData();
         } else {
         } else {
@@ -96,6 +96,13 @@ public abstract class BaseListFragment3<T> extends BaseRefreshLoadMoreFragment{
             refreshOrLoadMoreComplete();
             refreshOrLoadMoreComplete();
         }
         }
     }
     }
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
 
 
     protected List<T> list = ListUtil.emptyList();
     protected List<T> list = ListUtil.emptyList();
     protected List<T> lastCacheList = ListUtil.emptyList();
     protected List<T> lastCacheList = ListUtil.emptyList();

+ 8 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment4.java

@@ -55,13 +55,20 @@ public abstract class BaseListFragment4<T> extends BaseFragment {
 
 
     //加载更多数据
     //加载更多数据
     public void loadMoreData() {
     public void loadMoreData() {
-        if (ListUtil.size(list) >= per_page * page) {
+        if (hasMore()) {
             page += 1;
             page += 1;
             initData();
             initData();
         } else {
         } else {
             setNoMore(true);
             setNoMore(true);
         }
         }
     }
     }
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
 
 
     protected void setNoMore(boolean noMore) {
     protected void setNoMore(boolean noMore) {
         if (noMore)
         if (noMore)

+ 8 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment5.java

@@ -115,7 +115,7 @@ public abstract class BaseListFragment5<T> extends BaseFragment implements IRefr
     public void loadMoreData() {
     public void loadMoreData() {
         if (!loadMore) {
         if (!loadMore) {
             loadMore = true;
             loadMore = true;
-            if (ListUtil.size(list) >= per_page * page) {
+            if (hasMore()) {
                 page += 1;
                 page += 1;
                 initData();
                 initData();
             } else {
             } else {
@@ -125,6 +125,13 @@ public abstract class BaseListFragment5<T> extends BaseFragment implements IRefr
             finishRefresh();
             finishRefresh();
         }
         }
     }
     }
+    //还有数据没有获取
+    protected boolean hasMore() {
+        if(lastMessage != null && lastMessage.getTotal() > 0){
+            return lastMessage.getTotal() > ListUtil.size(list);
+        }
+        return ListUtil.size(list) >= per_page * page;
+    }
 
 
     protected void setNoMore(boolean noMore) {
     protected void setNoMore(boolean noMore) {
         if (noMore) {
         if (noMore) {

+ 41 - 39
app/src/main/java/com/sheep/gamegroup/view/fragment/BaseListFragment6.java

@@ -10,7 +10,7 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
 import com.chad.library.adapter.base.BaseViewHolder;
 import com.chad.library.adapter.base.BaseViewHolder;
 import com.chad.library.adapter.base.loadmore.LoadMoreView;
 import com.chad.library.adapter.base.loadmore.LoadMoreView;
 import com.sheep.gamegroup.absBase.AbsObserver;
 import com.sheep.gamegroup.absBase.AbsObserver;
-import com.sheep.gamegroup.absBase.ApiRefresh;
+import com.sheep.gamegroup.absBase.IApiRefresh;
 import com.sheep.gamegroup.absBase.ILoadMore;
 import com.sheep.gamegroup.absBase.ILoadMore;
 import com.sheep.gamegroup.absBase.IRefresh;
 import com.sheep.gamegroup.absBase.IRefresh;
 import com.sheep.gamegroup.util.ListUtil;
 import com.sheep.gamegroup.util.ListUtil;
@@ -23,7 +23,6 @@ import com.sheep.jiuyan.samllsheep.base.BaseFragment;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
 
 
-import butterknife.BindView;
 import rx.functions.Action1;
 import rx.functions.Action1;
 
 
 /**
 /**
@@ -43,6 +42,8 @@ public abstract class BaseListFragment6<T> extends BaseFragment implements IRefr
     @Override
     @Override
     public void onViewCreated() {
     public void onViewCreated() {
         activity = getActivity();
         activity = getActivity();
+        findView();
+        addApiRefresh(apiRefreshList);
         initView();
         initView();
         initListener();
         initListener();
         switch (refreshDataType()) {
         switch (refreshDataType()) {
@@ -53,28 +54,33 @@ public abstract class BaseListFragment6<T> extends BaseFragment implements IRefr
                 break;
                 break;
             case REFRESH_ON_YOURSELF:
             case REFRESH_ON_YOURSELF:
             default:
             default:
-                notifyDataSetChanged();
+                notifyDataSetChanged(1, true);
                 break;
                 break;
         }
         }
     }
     }
 
 
-    protected List<ApiRefresh<? extends Object>> apiRefreshList = new ArrayList<>();
+    protected abstract void addApiRefresh(List<IApiRefresh> apiRefreshList);
+
+    protected List<IApiRefresh> apiRefreshList = new ArrayList<>();
 
 
     public static final int REFRESH_ON_CREATE = 0;
     public static final int REFRESH_ON_CREATE = 0;
     public static final int REFRESH_ON_RESUME = 1;
     public static final int REFRESH_ON_RESUME = 1;
     public static final int REFRESH_ON_YOURSELF = -1;
     public static final int REFRESH_ON_YOURSELF = -1;
-    @BindView(R.id.title)
-    View title;
-    @BindView(R.id.check_net_ll)
-    View check_net_ll;
-    @BindView(R.id.swipeRefreshLayout)
-    SwipeRefreshLayout swipeRefreshLayout;
-    @BindView(R.id.recyclerView)
-    RecyclerView recyclerView;
+    protected View title;
+    protected View check_net_ll;
+    protected SwipeRefreshLayout swipeRefreshLayout;
+    protected RecyclerView recyclerView;
 
 
     protected BaseQuickAdapter<T, BaseViewHolder> baseQuickAdapter;
     protected BaseQuickAdapter<T, BaseViewHolder> baseQuickAdapter;
 
 
 
 
+    public void findView() {
+        title = findViewById(R.id.title);
+        check_net_ll = findViewById(R.id.check_net_ll);
+        swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
+        recyclerView = findViewById(R.id.recyclerView);
+    }
+
     public void initView() {
     public void initView() {
         ViewUtil.setVisibility(title, false);
         ViewUtil.setVisibility(title, false);
     }
     }
@@ -129,25 +135,14 @@ public abstract class BaseListFragment6<T> extends BaseFragment implements IRefr
     }
     }
 
 
     public void loadMoreData() {
     public void loadMoreData() {
-        ListUtil.forEach(apiRefreshList, new Action1<ApiRefresh<? extends Object>>() {
+        ListUtil.forEach(apiRefreshList, new Action1<IApiRefresh>() {
             @Override
             @Override
-            public void call(ApiRefresh<?> apiRefresh) {
-                if (apiRefresh.loadMoreData()) {
-                    finishRefresh();
-                }
+            public void call(IApiRefresh apiRefresh) {
+                apiRefresh.loadMoreData();
             }
             }
         });
         });
     }
     }
 
 
-    public void setNoMore(boolean noMore) {
-        if (noMore) {
-            baseQuickAdapter.loadMoreEnd();
-        } else {
-            baseQuickAdapter.loadMoreComplete();
-        }
-        finishRefresh();
-    }
-
     @Override
     @Override
     public void onResume() {
     public void onResume() {
         super.onResume();
         super.onResume();
@@ -168,23 +163,23 @@ public abstract class BaseListFragment6<T> extends BaseFragment implements IRefr
     public void refreshData() {
     public void refreshData() {
         checkMetLl();
         checkMetLl();
         clear();
         clear();
-        ListUtil.forEach(apiRefreshList, new Action1<ApiRefresh<? extends Object>>() {
+        ListUtil.forEach(apiRefreshList, new Action1<IApiRefresh>() {
             @Override
             @Override
-            public void call(ApiRefresh<?> apiRefresh) {
+            public void call(IApiRefresh apiRefresh) {
                 apiRefresh.clear();
                 apiRefresh.clear();
             }
             }
         });
         });
         ViewUtil.notifyDataSetChanged(recyclerView);
         ViewUtil.notifyDataSetChanged(recyclerView);
-        ListUtil.forEach(apiRefreshList, new Action1<ApiRefresh<? extends Object>>() {
+        ListUtil.forEach(apiRefreshList, new Action1<IApiRefresh>() {
             @Override
             @Override
-            public void call(ApiRefresh<?> apiRefresh) {
+            public void call(IApiRefresh apiRefresh) {
                 apiRefresh.initData();
                 apiRefresh.initData();
             }
             }
         });
         });
     }
     }
 
 
     protected void clear() {
     protected void clear() {
-        setNoMore(false);
+        notifyDataSetChanged(1, true);
         initLoadMoreListener();
         initLoadMoreListener();
     }
     }
 
 
@@ -199,23 +194,30 @@ public abstract class BaseListFragment6<T> extends BaseFragment implements IRefr
         }
         }
     }
     }
 
 
-    public void notifyDataSetChanged() {
+    public void notifyDataSetChanged(int page, boolean hasMore) {
         if (recyclerView == null)
         if (recyclerView == null)
             recyclerView = findViewById(R.id.recyclerView);
             recyclerView = findViewById(R.id.recyclerView);
-        ListUtil.forEach(apiRefreshList, new Action1<ApiRefresh<? extends Object>>() {
+        ListUtil.forEach(apiRefreshList, new Action1<IApiRefresh>() {
             @Override
             @Override
-            public void call(ApiRefresh<?> apiRefresh) {
+            public void call(IApiRefresh apiRefresh) {
                 apiRefresh.setLoadMore(false);
                 apiRefresh.setLoadMore(false);
             }
             }
         });
         });
         ViewUtil.notifyDataSetChanged(recyclerView);
         ViewUtil.notifyDataSetChanged(recyclerView);
-        finishRefresh();
+        if (hasMore) {
+            switch (page) {
+                case 1:
+                    if (swipeRefreshLayout != null)
+                        swipeRefreshLayout.setRefreshing(false);
+                default:
+                    baseQuickAdapter.loadMoreComplete();
+                    break;
+            }
+        } else {
+            baseQuickAdapter.loadMoreEnd(false);
+        }
     }
     }
 
 
-    protected void finishRefresh() {
-        if (swipeRefreshLayout != null)
-            swipeRefreshLayout.setRefreshing(false);
-    }
 
 
     @Override
     @Override
     public void onDestroyView() {
     public void onDestroyView() {

+ 0 - 1
app/src/main/java/com/sheep/gamegroup/view/fragment/FgtArticleVideo.java

@@ -76,5 +76,4 @@ public class FgtArticleVideo extends BaseListFragment2<DiscoveryVideo> {
         }
         }
     }
     }
 
 
-
 }
 }

+ 83 - 0
app/src/main/java/com/sheep/gamegroup/view/fragment/FgtDiscoveryTopic.java

@@ -0,0 +1,83 @@
+package com.sheep.gamegroup.view.fragment;
+
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.BaseViewHolder;
+import com.sheep.gamegroup.absBase.IApiRefresh;
+import com.sheep.gamegroup.absBase.NetApiRefresh;
+import com.sheep.gamegroup.model.api.ApiService;
+import com.sheep.gamegroup.model.entity.BaseMessage;
+import com.sheep.gamegroup.model.entity.DiscoveryTopic;
+import com.sheep.jiuyan.samllsheep.R;
+
+import org.afinal.simplecache.ApiKey;
+import org.greenrobot.eventbus.EventBus;
+
+import java.util.List;
+
+import io.reactivex.Observable;
+
+/**
+ * Created by realicing on 2018/11/29.
+ * realicing@sina.com
+ * 小绵羊3.4.5新增 -- 为视频添加话题,话题列表
+ */
+public class FgtDiscoveryTopic extends BaseListFragment6<DiscoveryTopic> {
+
+    @Override
+    public int getLayoutId() {
+        return R.layout.common_srl_rv;
+    }
+
+    private NetApiRefresh<DiscoveryTopic> mApiRefresh;
+    @Override
+    protected void addApiRefresh(List<IApiRefresh> apiRefreshList) {
+        mApiRefresh = new NetApiRefresh<DiscoveryTopic>(this) {
+            @Override
+            protected boolean hasMore() {
+                return false;
+            }
+
+            @Override
+            public String getKey(int page, int per_page) {
+                return ApiKey.getVideoTopic;
+            }
+
+            @Override
+            public Observable<BaseMessage> getApi(ApiService apiService) {
+                return apiService.getVideoTopic();
+            }
+
+            @Override
+            public Class<DiscoveryTopic> getTClass() {
+                return DiscoveryTopic.class;
+            }
+        };
+        apiRefreshList.add(mApiRefresh);
+    }
+
+    @Override
+    protected BaseQuickAdapter<DiscoveryTopic, BaseViewHolder> getAdapter() {
+        return new BaseQuickAdapter<DiscoveryTopic, BaseViewHolder>(R.layout.item_discovery_topic, mApiRefresh.getList()) {
+            @Override
+            protected void convert(BaseViewHolder helper, DiscoveryTopic item) {
+                helper.setText(R.id.item_discovery_topic_content, item.getTopic());
+            }
+        };
+    }
+
+    @Override
+    public void initListener() {
+        super.initListener();
+        baseQuickAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
+            @Override
+            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
+                DiscoveryTopic item = mApiRefresh.getItem(position);
+                if(item != null) {
+                    EventBus.getDefault().post(item);
+                }
+            }
+        });
+    }
+}

+ 6 - 6
app/src/main/java/com/sheep/gamegroup/view/fragment/FgtUserFocusLogList.java

@@ -9,7 +9,8 @@ import android.widget.TextView;
 
 
 import com.chad.library.adapter.base.BaseQuickAdapter;
 import com.chad.library.adapter.base.BaseQuickAdapter;
 import com.chad.library.adapter.base.BaseViewHolder;
 import com.chad.library.adapter.base.BaseViewHolder;
-import com.sheep.gamegroup.absBase.ApiRefresh;
+import com.sheep.gamegroup.absBase.IApiRefresh;
+import com.sheep.gamegroup.absBase.NetApiRefresh;
 import com.sheep.gamegroup.model.api.ApiService;
 import com.sheep.gamegroup.model.api.ApiService;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.BaseMessage;
 import com.sheep.gamegroup.model.entity.UserFocusLog;
 import com.sheep.gamegroup.model.entity.UserFocusLog;
@@ -51,10 +52,10 @@ public class FgtUserFocusLogList extends BaseListFragment6<String> {
     };
     };
 
 
     @Override
     @Override
-    public void initView() {
+    protected void addApiRefresh(List<IApiRefresh> apiRefreshList) {
         tagList.add("1");
         tagList.add("1");
         tagList.add("2");
         tagList.add("2");
-        ApiRefresh<UserFocusLog> apiRefresh1 = new ApiRefresh<UserFocusLog>(this) {
+        NetApiRefresh<UserFocusLog> apiRefresh1 = new NetApiRefresh<UserFocusLog>(this) {
             @Override
             @Override
             public String getKey(int page, int per_page) {
             public String getKey(int page, int per_page) {
                 return ApiKey.pageKeyUrl(ApiKey.getGameUserUserFocusList, page, per_page);
                 return ApiKey.pageKeyUrl(ApiKey.getGameUserUserFocusList, page, per_page);
@@ -67,10 +68,10 @@ public class FgtUserFocusLogList extends BaseListFragment6<String> {
 
 
             @Override
             @Override
             public Class<UserFocusLog> getTClass() {
             public Class<UserFocusLog> getTClass() {
-                return null;
+                return UserFocusLog.class;
             }
             }
         };
         };
-        ApiRefresh<UserFocusLog> apiRefresh2 = new ApiRefresh<UserFocusLog>(this) {
+        NetApiRefresh<UserFocusLog> apiRefresh2 = new NetApiRefresh<UserFocusLog>(this) {
             @Override
             @Override
             public String getKey(int page, int per_page) {
             public String getKey(int page, int per_page) {
                 return ApiKey.pageKeyUrl(ApiKey.getGameUserUserFocusHotUser, page, per_page);
                 return ApiKey.pageKeyUrl(ApiKey.getGameUserUserFocusHotUser, page, per_page);
@@ -108,7 +109,6 @@ public class FgtUserFocusLogList extends BaseListFragment6<String> {
         adpUserFocusLogList2 = new AdpUserFocusLogList(apiRefresh2.getList());
         adpUserFocusLogList2 = new AdpUserFocusLogList(apiRefresh2.getList());
         adpUserFocusLogList.setAction1(action1);
         adpUserFocusLogList.setAction1(action1);
         adpUserFocusLogList2.setAction1(action1);
         adpUserFocusLogList2.setAction1(action1);
-        super.initView();
     }
     }
 
 
     private View headerView;
     private View headerView;

+ 34 - 0
app/src/main/java/com/sheep/jiuyan/samllsheep/base/BaseFragment.java

@@ -7,11 +7,18 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup;
 
 
+import com.sheep.gamegroup.absBase.AbsObserver;
+import com.sheep.gamegroup.util.ActionUtil;
 import com.sheep.gamegroup.view.dialog.DialogLoading;
 import com.sheep.gamegroup.view.dialog.DialogLoading;
 import com.trello.rxlifecycle2.components.support.RxFragment;
 import com.trello.rxlifecycle2.components.support.RxFragment;
 
 
+import java.util.concurrent.TimeUnit;
+
 import butterknife.ButterKnife;
 import butterknife.ButterKnife;
 import butterknife.Unbinder;
 import butterknife.Unbinder;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
 
 
 /**
 /**
  * @ Created by Dlg
  * @ Created by Dlg
@@ -163,4 +170,31 @@ public abstract class BaseFragment extends RxFragment {
     public boolean userButterKnife() {
     public boolean userButterKnife() {
         return true;
         return true;
     }
     }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        checkNextAction(this.getClass().getSimpleName());
+    }
+
+    protected boolean checkNextAction(String key) {
+        final Object action = ActionUtil.getInstance().getAction(key);
+        if (action != null) {
+            //延时一会儿,不然有可能操作会无效
+            Observable.just(1).delay(50L, TimeUnit.MILLISECONDS)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .subscribe(new AbsObserver<Integer>() {
+                        @Override
+                        public void onNext(Integer integer) {
+                            doNextAction(action);
+                        }
+                    });
+            return true;
+        }
+        return false;
+    }
+    public void doNextAction(Object action) {
+
+    }
 }
 }

+ 23 - 4
app/src/main/java/com/sheep/jiuyan/samllsheep/service/DownloadService.java

@@ -26,6 +26,7 @@ import com.liulishuo.okdownload.core.listener.DownloadListener4WithSpeed;
 import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend;
 import com.liulishuo.okdownload.core.listener.assist.Listener4SpeedAssistExtend;
 import com.sheep.gamegroup.event.BigEvent;
 import com.sheep.gamegroup.event.BigEvent;
 import com.sheep.gamegroup.event.EventTypes;
 import com.sheep.gamegroup.event.EventTypes;
+import com.sheep.gamegroup.greendao.DDProviderHelper;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
 import com.sheep.gamegroup.greendao.download.DownLoadInfo;
 import com.sheep.gamegroup.model.entity.Applications;
 import com.sheep.gamegroup.model.entity.Applications;
 import com.sheep.gamegroup.model.entity.TaskEty;
 import com.sheep.gamegroup.model.entity.TaskEty;
@@ -76,6 +77,7 @@ public class DownloadService extends Service {
         @Override
         @Override
         public void taskStart(@NonNull DownloadTask task) {
         public void taskStart(@NonNull DownloadTask task) {
             LogUtil.println("DownloadListener", "taskStart");
             LogUtil.println("DownloadListener", "taskStart");
+            DDProviderHelper.getInstance().updateDownload(task.getId(), task.getUrl(), DownloadUtil.STATUS_INIT);
         }
         }
 
 
         @Override
         @Override
@@ -125,19 +127,36 @@ public class DownloadService extends Service {
                         EventBus.getDefault().post(new BigEvent().setEventTypes(EventTypes.DOWNLOAD_COMPLETE).setData(downLoadInfo));
                         EventBus.getDefault().post(new BigEvent().setEventTypes(EventTypes.DOWNLOAD_COMPLETE).setData(downLoadInfo));
                     }
                     }
                     break;
                     break;
-                case FILE_BUSY:
                 case PRE_ALLOCATE_FAILED://预先分配失败
                 case PRE_ALLOCATE_FAILED://预先分配失败
-                case ERROR://下载错误
-                    downLoadInfo = downloadUtil.setDownloadTaskStatus(task.getUrl(), DownloadUtil.STATUS_FAIL);
+                    //空间不足,弹框提示
+                    try {
+                        DialogStorageLow.showDialog(realCause != null ? realCause.getMessage() : null);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                    downLoadInfo = downloadUtil.getDownloadTaskByUrl(task.getUrl());
+                    downLoadInfo.setMStatus(DownloadUtil.STATUS_FAIL);
+                    if(realCause != null)
+                        downLoadInfo.setRealCauseMsg(realCause.getMessage());
+                    DDProviderHelper.getInstance().updateDownload(downLoadInfo);
                     EventBus.getDefault().post(new BigEvent().setEventTypes(EventTypes.DOWNLOAD_FAIL).setData(downLoadInfo));
                     EventBus.getDefault().post(new BigEvent().setEventTypes(EventTypes.DOWNLOAD_FAIL).setData(downLoadInfo));
+                    break;
+                case FILE_BUSY:
+                case ERROR://下载错误
                     //空间不足,弹框提示
                     //空间不足,弹框提示
                     try {
                     try {
                         if (0 <= task.getReadBufferSize() && task.getReadBufferSize() > G.getFreeSpaceB()) {
                         if (0 <= task.getReadBufferSize() && task.getReadBufferSize() > G.getFreeSpaceB()) {
-                            DialogStorageLow.showDialog(DownloadService.this);
+                            DialogStorageLow.showDialog(realCause != null ? realCause.getMessage() : null);
                         }
                         }
                     } catch (Exception e) {
                     } catch (Exception e) {
                         e.printStackTrace();
                         e.printStackTrace();
                     }
                     }
+                    downLoadInfo = downloadUtil.getDownloadTaskByUrl(task.getUrl());
+                    downLoadInfo.setMStatus(DownloadUtil.STATUS_FAIL);
+                    if(realCause != null)
+                        downLoadInfo.setRealCauseMsg(realCause.getMessage());
+                    DDProviderHelper.getInstance().updateDownload(downLoadInfo);
+                    EventBus.getDefault().post(new BigEvent().setEventTypes(EventTypes.DOWNLOAD_FAIL).setData(downLoadInfo));
                     break;
                     break;
                 case CANCELED://取消下载
                 case CANCELED://取消下载
                     downLoadInfo = downloadUtil.setDownloadTaskStatus(task.getUrl(), DownloadUtil.STATUS_PAUSE);
                     downLoadInfo = downloadUtil.setDownloadTaskStatus(task.getUrl(), DownloadUtil.STATUS_PAUSE);

+ 1 - 1
app/src/main/java/com/sheep/jiuyan/samllsheep/utils/G.java

@@ -239,7 +239,7 @@ public class G {
                     file.length() > getFreeSpaceB() / 2
                     file.length() > getFreeSpaceB() / 2
                             && file.length() > getSdkFreeSpace() / 2
                             && file.length() > getSdkFreeSpace() / 2
             )) {
             )) {
-                DialogStorageLow.showDialog(context);
+                DialogStorageLow.showDialog(null);
             }
             }
         }catch (Exception e){
         }catch (Exception e){
             e.printStackTrace();
             e.printStackTrace();

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

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

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

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

+ 6 - 0
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>

+ 10 - 0
app/src/main/res/layout/act_cut_video.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#000000"
+    tools:context="com.sheep.gamegroup.view.activity.ActEditVideo">
+
+</android.support.constraint.ConstraintLayout>

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

@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="#000000"
+    tools:context="com.sheep.gamegroup.view.activity.ActEditVideo">
+
+    <VideoView
+        android:id="@+id/videoView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#99000000" />
+
+    <com.github.ybq.android.spinkit.SpinKitView
+        android:id="@+id/video_loading"
+        style="@style/SpinKitView.Large.ThreeBounce"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:SpinKit_Color="@color/colorAccent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <ImageView
+        android:id="@+id/video_back_iv"
+        android:layout_width="?attr/actionBarSize"
+        android:layout_height="?attr/actionBarSize"
+        android:layout_marginTop="20dp"
+        android:onClick="onClickBackImg"
+        android:scaleType="centerInside"
+        android:src="@drawable/narrow_back_white"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <TextView
+        android:id="@+id/edit_video_topic_tv"
+        android:layout_width="0dp"
+        android:layout_height="30dp"
+        android:background="@drawable/shape_white_20_solid_rectangle_15"
+        android:gravity="center|start"
+        android:maxLength="100"
+        android:onClick="onClickTopic"
+        android:paddingStart="18dp"
+        android:paddingEnd="18dp"
+        android:text="#添加话题#"
+        android:textColor="#FEFFFF"
+        android:textSize="13sp"
+        app:layout_constraintBottom_toBottomOf="@id/video_back_iv"
+        app:layout_constraintEnd_toStartOf="@id/edit_video_sure_tv"
+        app:layout_constraintStart_toEndOf="@id/video_back_iv"
+        app:layout_constraintTop_toTopOf="@id/video_back_iv" />
+
+    <TextView
+        android:id="@+id/edit_video_sure_tv"
+        android:layout_width="75dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="31dp"
+        android:layout_marginEnd="16dp"
+        android:background="@drawable/selector_button_full_main"
+        android:gravity="center"
+        android:onClick="onClickSure"
+        android:paddingTop="6dp"
+        android:paddingBottom="6dp"
+        android:text="下一步"
+        android:textColor="#FEFFFF"
+        android:textSize="15sp"
+        app:layout_constraintBottom_toBottomOf="@id/video_back_iv"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toEndOf="@id/edit_video_topic_tv"
+        app:layout_constraintTop_toTopOf="@id/video_back_iv" />
+
+    <FrameLayout
+        android:id="@+id/frame_container"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginTop="27dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/edit_video_topic_tv" />
+
+    <com.sheep.gamegroup.view.customview.VideoFramesView
+        android:id="@+id/videoFramesView"
+        android:layout_width="match_parent"
+        android:layout_height="69dp"
+        android:layout_marginStart="36dp"
+        android:layout_marginEnd="36dp"
+        android:layout_marginBottom="17dp"
+        app:layout_constraintBottom_toBottomOf="parent" />
+
+    <TextView
+        android:id="@+id/edit_video_time_tv"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="15dp"
+        android:layout_marginBottom="100dp"
+        android:text="@string/has_choose_x_second"
+        android:textColor="#ffffffff"
+        android:textSize="12sp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintStart_toStartOf="parent" />
+</android.support.constraint.ConstraintLayout>

+ 22 - 0
app/src/main/res/layout/act_media_choose.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@color/white"
+    android:orientation="vertical">
+
+    <include layout="@layout/title" />
+
+    <android.support.design.widget.TabLayout
+        android:id="@+id/indicator"
+        style="@style/style_tab"
+        android:layout_marginTop="7dp" />
+
+    <include layout="@layout/line_1px_hor" />
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/viewPager"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+</LinearLayout>

+ 59 - 0
app/src/main/res/layout/custom_video_frames_view.xml

@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="69dp"
+    android:layout_marginStart="36dp"
+    android:layout_marginEnd="36dp"
+    android:layout_marginBottom="17dp"
+    app:layout_constraintBottom_toBottomOf="parent">
+
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="61dp"
+        android:layout_marginTop="4dp"
+        android:layout_marginBottom="4dp"
+        android:background="#000" />
+
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginStart="12dp"
+        android:layout_marginTop="8dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginBottom="8dp"
+        android:orientation="horizontal"
+        app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
+
+    <View
+        android:id="@+id/line_start"
+        android:layout_width="6dp"
+        android:layout_height="match_parent"
+        android:layout_alignStart="@id/recyclerView"
+        android:background="@drawable/shape_white_solid_rectangle_5" />
+
+    <View
+        android:id="@+id/line_end"
+        android:layout_width="6dp"
+        android:layout_height="match_parent"
+        android:layout_alignEnd="@id/recyclerView"
+        android:background="@drawable/shape_white_solid_rectangle_5" />
+
+    <include
+        layout="@layout/include_lll"
+        android:layout_width="5dp"
+        android:layout_height="20dp"
+        android:layout_alignParentEnd="true"
+        android:layout_centerVertical="true"
+        android:layout_marginEnd="3dp" />
+
+    <include
+        layout="@layout/include_lll"
+        android:layout_width="5dp"
+        android:layout_height="20dp"
+        android:layout_alignParentStart="true"
+        android:layout_centerVertical="true"
+        android:layout_marginStart="3dp" />
+
+</RelativeLayout>

+ 34 - 0
app/src/main/res/layout/include_lll.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal">
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="#B0AFAF" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="#B0AFAF" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1" />
+
+    <View
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="#B0AFAF" />
+</LinearLayout>

+ 20 - 0
app/src/main/res/layout/item_discovery_topic.xml

@@ -0,0 +1,20 @@
+<?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="wrap_content">
+
+    <TextView
+        android:id="@+id/item_discovery_topic_content"
+        android:layout_width="wrap_content"
+        android:layout_height="30dp"
+        android:layout_centerHorizontal="true"
+        android:layout_margin="10dp"
+        android:background="@drawable/shape_white_20_solid_rectangle_15"
+        android:gravity="center"
+        android:maxLength="100"
+        android:paddingStart="18dp"
+        android:paddingEnd="18dp"
+        android:text="#添加话题#"
+        android:textColor="#FEFFFF"
+        android:textSize="13sp" />
+</RelativeLayout>

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

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/item_iv"
+    android:layout_width="wrap_content"
+    android:layout_height="match_parent"
+    android:scaleType="fitXY" />

+ 29 - 0
app/src/main/res/layout/item_media_picker.xml

@@ -0,0 +1,29 @@
+<?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="wrap_content">
+
+    <ImageView
+        android:id="@+id/item_media_picker_iv"
+        android:layout_width="match_parent"
+        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
+        android:layout_marginTop="6dp"
+        android:layout_marginBottom="6dp"
+        android:layout_height="wrap_content"
+        android:adjustViewBounds="true"
+        android:scaleType="fitXY" />
+
+    <TextView
+        android:id="@+id/item_media_picker_tv"
+        android:layout_width="20dp"
+        android:layout_height="20dp"
+        android:layout_alignTop="@id/item_media_picker_iv"
+        android:layout_alignEnd="@id/item_media_picker_iv"
+        android:layout_margin="10dp"
+        android:background="@drawable/shape_oval_solid_10_f5"
+        android:gravity="center"
+        android:text="√"
+        android:textColor="@color/yellow_D3AF57"
+        android:textSize="12sp" />
+</RelativeLayout>

+ 4 - 4
app/src/main/res/layout/line_1px_hor.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <View xmlns:android="http://schemas.android.com/apk/res/android"
 <View xmlns:android="http://schemas.android.com/apk/res/android"
-      android:layout_width="match_parent"
-      android:layout_height="1px"
-      android:background="@color/gray_5">
-</View>
+    android:id="@+id/below_tab_line"
+    android:layout_width="match_parent"
+    android:layout_height="1px"
+    android:background="@color/gray_5"/>

BIN
app/src/main/res/mipmap-xxhdpi/ic_open_camera.webp


+ 1 - 0
app/src/main/res/values/colors.xml

@@ -9,5 +9,6 @@
     <color name="green">#4cd117</color>
     <color name="green">#4cd117</color>
 
 
     <color name="bg_class_grey">#f9f9f9</color>
     <color name="bg_class_grey">#f9f9f9</color>
+    <color name="gray_CBCBCB">#cbcbcb</color>
 
 
 </resources>
 </resources>

+ 2 - 0
app/src/main/res/values/strings.xml

@@ -141,4 +141,6 @@
     <string name="hot_user">热门玩家</string>
     <string name="hot_user">热门玩家</string>
     <!--小绵羊3.4.5新增功能 发布发现-->
     <!--小绵羊3.4.5新增功能 发布发现-->
     <string name="please_say_something">说点什么~</string>
     <string name="please_say_something">说点什么~</string>
+    <string name="jin_x_jin">#%s#</string>
+    <string name="has_choose_x_second">已选取 %s秒</string>
 </resources>
 </resources>

+ 1 - 1
settings.gradle

@@ -1 +1 @@
-include ':app', ':view', ':ucrop', ':WaterWaveProgress', ':RxGalleryFinal'//, ':Aria', ':datashare', ':AriaAnnotations'
+include ':app', ':view', ':ucrop', ':WaterWaveProgress'//, ':RxGalleryFinal', ':Aria', ':datashare', ':AriaAnnotations'

+ 6 - 4
view/src/main/java/com/kfzs/android/view/widget/WrapContentHeightViewPager.java

@@ -45,10 +45,12 @@ public class WrapContentHeightViewPager extends ViewPager {
             @Override
             @Override
             public void onPageSelected(int position) {
             public void onPageSelected(int position) {
                 View view = getChildAt(position);
                 View view = getChildAt(position);
-                int height = view.getMeasuredHeight();
-                ViewGroup.LayoutParams layoutParams = getLayoutParams();
-                layoutParams.height = height;
-                setLayoutParams(layoutParams);
+                if(view != null) {
+                    int height = view.getMeasuredHeight();
+                    ViewGroup.LayoutParams layoutParams = getLayoutParams();
+                    layoutParams.height = height;
+                    setLayoutParams(layoutParams);
+                }
             }
             }
 
 
             @Override
             @Override