Commit 7f47a40d authored by linfeng's avatar linfeng

短视频

parent 928f79d8
......@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.util.Log;
import com.google.gson.Gson;
......@@ -45,6 +46,13 @@ public class OkGoUtil {
final private static String SP_KEY_USERINFO = "userinfo";
/* 文件缓存的目录 */
public String mAppDir;
public String mPicturesDir;
public String mVoicesDir;
public String mVideosDir;
public String mFilesDir;
public static String getYkId() {
String ykid = "uk_" + (int) ((Math.random() * 9 + 1) * 100000);
return ykid;
......@@ -152,6 +160,50 @@ public class OkGoUtil {
}
}
private void initAppDir() {
File file = application.getExternalFilesDir(null);
if (file != null && !file.exists()) {
file.mkdirs();
}
if (file != null) {
mAppDir = file.getAbsolutePath();
}
file = application.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (file != null && !file.exists()) {
file.mkdirs();
}
if (file != null) {
mPicturesDir = file.getAbsolutePath();
}
file = application.getExternalFilesDir(Environment.DIRECTORY_MUSIC);
if (file != null && !file.exists()) {
file.mkdirs();
}
if (file != null) {
mVoicesDir = file.getAbsolutePath();
}
file = application.getExternalFilesDir(Environment.DIRECTORY_MOVIES);
if (file != null && !file.exists()) {
file.mkdirs();
}
if (file != null) {
mVideosDir = file.getAbsolutePath();
}
file = application.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
if (file != null && !file.exists()) {
file.mkdirs();
}
if (file != null) {
mFilesDir = file.getAbsolutePath();
}
}
//上传文件
public static void upload(String url, File file) {
// 特别要注意的是
......
......@@ -8,8 +8,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
flavorDimensions "default"
versionCode 154
versionName "1.5.4"
versionCode 155
versionName "1.5.5"
multiDexEnabled true
......
......@@ -87,5 +87,7 @@ android {
api files('libs/umeng-share-wechat-simplify-6.9.4.jar')
api files('libs/umeng-shareboard-widget-6.9.4.jar')
api files('libs/umeng-sharetool-6.9.4.jar')
api files('libs/ormlite-android-4.48.jar')
api files('libs/ormlite-core-4.48.jar')
}
}
......@@ -13,7 +13,7 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application>
<activity android:name=".other.SelectVideoActivity"></activity>
<activity android:name="com.xxrv.video.activity.SelectVideoActivity"></activity>
<activity
android:name=".other.ShortVideoActivity"
android:screenOrientation="portrait" />
......
......@@ -11,13 +11,13 @@ import com.ruiwenliu.wrapper.util.TransformationUtil;
import com.ruiwenliu.wrapper.util.glide.GlideManager;
import com.ruiwenliu.wrapper.util.glide.GlideOptions;
import com.xxfc.discovery.R;
import com.xxfc.discovery.bean.DiscoveryRecommendBean;
import com.xxrv.video.bean.circle.DiscoveryVideoBean;
/**
* 短视频
*/
public class DiscoveryShortVideoAdapter extends BaseQuickAdapter<DiscoveryRecommendBean.DataBeanX.DataBean, BaseViewHolder> {
public class DiscoveryShortVideoAdapter extends BaseQuickAdapter<DiscoveryVideoBean.DataBeanX.DataBean, BaseViewHolder> {
public DiscoveryShortVideoAdapter() {
super(R.layout.rv_item_discovery_short_video);
......@@ -25,12 +25,12 @@ public class DiscoveryShortVideoAdapter extends BaseQuickAdapter<DiscoveryRecomm
@Override
protected void convert(BaseViewHolder helper, DiscoveryRecommendBean.DataBeanX.DataBean item) {
protected void convert(BaseViewHolder helper, DiscoveryVideoBean.DataBeanX.DataBean item) {
if (item == null) {
return;
}
DiscoveryRecommendBean.DataBeanX.DataBean.Body body = item.getBody();
DiscoveryVideoBean.DataBeanX.DataBean.Body body = item.getBody();
if (body != null) {
if (body.getVideos() != null && body.getVideos().size() > 0) {
......
......@@ -12,6 +12,7 @@ import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import com.xxfc.discovery.R;
/**
......@@ -25,7 +26,7 @@ public class TrillCommentInputDialog extends Dialog {
private OnSendCommentListener mOnSendCommentListener;
public TrillCommentInputDialog(Context context, OnSendCommentListener onSendCommentListener) {
super(context, R.style.BottomDialog);;
super(context, R.style.BottomDialog);
this.mOnSendCommentListener = onSendCommentListener;
}
......
......@@ -2,35 +2,27 @@ package com.xxfc.discovery.fragment;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.Display;
import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.base.url.Constance;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseFragment;
import com.ruiwenliu.wrapper.weight.refresh.SimpleRefreshLayout;
import com.ruiwenliu.wrapper.weight.refresh.SimpleRefreshView;
import com.xxfc.discovery.R;
import com.xxfc.discovery.R2;
import com.xxfc.discovery.adapter.DiscoveryRecommendAdapter;
import com.xxfc.discovery.adapter.DiscoveryShortVideoAdapter;
import com.xxfc.discovery.api.DiscoveryApi;
import com.xxfc.discovery.bean.DiscoveryRecommendBean;
import com.xxfc.discovery.event.PostPatEvent;
import com.xxfc.discovery.event.PostVideoEvent;
import com.xxfc.discovery.other.ShortVideoActivity;
import com.xxfc.discovery.presenter.DiscoveryPresenter;
import com.xxrv.video.activity.TriListActivity;
import com.xxrv.video.bean.circle.DiscoveryVideoBean;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.schedulers.Schedulers;
......@@ -96,10 +88,10 @@ public class ShortVideoFragment extends BaseFragment<DiscoveryPresenter> impleme
mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
// DiscoveryRecommendBean.DataBeanX.DataBean data = (DiscoveryRecommendBean.DataBeanX.DataBean) adapter.getData();
DiscoveryRecommendBean.DataBeanX.DataBean item = (DiscoveryRecommendBean.DataBeanX.DataBean) adapter.getItem(position);
if (item != null) {
startActivity(ShortVideoActivity.getIntent(_mActivity, item));
List<DiscoveryVideoBean.DataBeanX.DataBean> data = adapter.getData();
// DiscoveryRecommendBean.DataBeanX.DataBean item = (DiscoveryRecommendBean.DataBeanX.DataBean) adapter.getItem(position);
if (data != null && data.size() > 0) {
startActivity(TriListActivity.getIntent(_mActivity, position, mPage, data));
}
}
});
......@@ -159,16 +151,16 @@ public class ShortVideoFragment extends BaseFragment<DiscoveryPresenter> impleme
Map<String, Object> map = new LinkedHashMap<>();
map.put("page", page);
map.put("type", 4);
mPresenter.postData(0, DiscoveryApi.DISCOVERY_UNAUTH_LIST, DiscoveryRecommendBean.class, map, page == 1 ? false : false);
mPresenter.postData(0, DiscoveryApi.DISCOVERY_UNAUTH_LIST, DiscoveryVideoBean.class, map, page == 1 ? false : false);
}
@Override
public void onShowResult(int requestType, BaseBean result) {
mSimpleRefreshLayout.onRefreshComplete();
processData((DiscoveryRecommendBean) result);
processData((DiscoveryVideoBean) result);
}
private void processData(DiscoveryRecommendBean bean) {
private void processData(DiscoveryVideoBean bean) {
if (mPage == 1) {
countPage = bean.getData().getTotalPage();
mAdapter.setNewData(bean.getData().getList());
......
......@@ -2,11 +2,10 @@ package com.xxfc.discovery.other;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
......@@ -15,6 +14,7 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.alibaba.fastjson.JSON;
......@@ -22,20 +22,18 @@ import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.Poi;
import com.baidu.mapapi.model.LatLng;
import com.base.utils.ui.datetime.selector.util.TextUtil;
import com.frame.base.bus.RxBus;
import com.frame.base.url.Constance;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
import com.ruiwenliu.wrapper.http.ProgressRequestBody;
import com.ruiwenliu.wrapper.inter.UploadCallbacks;
import com.ruiwenliu.wrapper.util.LocationManager;
import com.ruiwenliu.wrapper.util.ViewHolder;
import com.ruiwenliu.wrapper.util.glide.GlideManager;
import com.ruiwenliu.wrapper.util.permission.RxPermission;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.rv.component.dialog.ProgressBarDialog;
import com.rv.component.dialog.TipsDialog;
import com.rv.component.utils.DateUtils;
import com.xxfc.discovery.R;
import com.xxfc.discovery.R2;
......@@ -43,10 +41,10 @@ import com.xxfc.discovery.api.DiscoveryApi;
import com.xxfc.discovery.bean.DiscoveryIMTokenBean;
import com.xxfc.discovery.bean.ImageSources;
import com.xxfc.discovery.bean.UpdateVideoFile;
import com.xxfc.discovery.bean.VideoFile;
import com.xxfc.discovery.event.PostPatEvent;
import com.xxrv.video.bean.circle.VideoFile;
import com.xxfc.discovery.event.PostVideoEvent;
import com.xxfc.discovery.presenter.DiscoveryPresenter;
import com.xxrv.video.activity.SelectVideoActivity;
import com.yuyife.okgo.OkGoUtil;
import java.io.File;
......@@ -56,7 +54,6 @@ import java.util.List;
import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.functions.Consumer;
import okhttp3.MediaType;
......@@ -87,7 +84,19 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
private String address;
private String name;
private UpdateVideoFile videoBean;
private UpdateVideoFile imageBean;
private ArrayList<ImageSources> sourcesList;
private ArrayList<ImageSources> sourcesList2;
@Autowired()
String mVideoFilePath;
@Autowired()
long mTimeLen;
@Autowired()
String mThumbPath;
@Autowired()
String mCurrBgmId;
@Override
protected int setLayout() {
......@@ -97,6 +106,8 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
@Override
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
titleView.setTitle("发布视频");
GlideManager.getInstance(mActivity).loadImage(mThumbPath, ivVideoHint);
permissionProcess();
}
......@@ -105,6 +116,11 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
switch (requestType) {
case 0:
videoBean = (UpdateVideoFile) result;
uploadFile2(new File(mThumbPath), "Image");
break;
case 3:
imageBean = (UpdateVideoFile) result;
upData();
break;
case 1:
DiscoveryIMTokenBean intokenBean = (DiscoveryIMTokenBean) result;
......@@ -135,15 +151,19 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
map.put("text", etVideoContent.getText().toString());
sourcesList = new ArrayList<>();
ImageSources sources = new ImageSources();
sources.setoUrl(videoBean.getData());
sources.settUrl(videoBean.getData());
sourcesList.add(sources);
map.put("videos", JSON.toJSONString(sourcesList));
sourcesList2 = new ArrayList<>();
ImageSources sources2 = new ImageSources();
sources2.setoUrl(imageBean.getData());
sources2.settUrl(imageBean.getData());
sourcesList2.add(sources2);
map.put("images", JSON.toJSONString(sourcesList2));
if (!TextUtils.isEmpty(address)) {
addrStr = address;
// 纬度
......@@ -153,6 +173,9 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
// 位置
map.put("location", address);
}
if (!TextUtil.isEmpty(mCurrBgmId)) {
map.put("musicId", mCurrBgmId);
}
map.put("cityId", "0");
map.put("time", DateUtils.getCurTimeMillis());
mPresenter.postData(2, DiscoveryApi.DISCOVERY_MSG_ADD, BaseBean.class, map, true);
......@@ -174,7 +197,8 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
.withString("addrStr", addrStr)
.navigation(this, 211);
} else if (id == R.id.tv_video_ok) {
upData();
uploadFile(new File(mVideoFilePath), "video");
} else if (id == R.id.iv_item_delete) {
tvPatAddress.setText("");
latLatitude = 0;
......@@ -230,14 +254,32 @@ public class SendVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
mPresenter.getUploadFile(RvFrameConfig.VEHICLE_UPLOAD, 0, DiscoveryApi.HTTP_URL_FILE_UPLOAD_VIDEO, UpdateVideoFile.class, description, body, false);
}
/**
* 上传文件
*
* @param file
*/
private void uploadFile2(File file, String fileName) {
RequestBody requestFile =
RequestBody.create(MediaType.parse("application/otcet-stream"), file);
MultipartBody.Part body =
MultipartBody.Part.createFormData("file", file.getName(), requestFile);
RequestBody description =
RequestBody.create(
MediaType.parse("multipart/form-data"), fileName);
mPresenter.getUploadFile(RvFrameConfig.VEHICLE_UPLOAD, 3, DiscoveryApi.HTTP_URL_FILE_UPLOAD, UpdateVideoFile.class, description, body, false);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 109 && resultCode == 201) {
VideoFile videofile = (VideoFile) data.getSerializableExtra("videofile");
GlideManager.getInstance(mActivity).loadImage(videofile.getFilePath(), ivVideoHint);
uploadFile(new File(videofile.getFilePath()), "video");
// uploadFile(new File(videofile.getFilePath()), "video");
} else if (requestCode == 211 && resultCode == Activity.RESULT_OK) {
ivItemDelete.setVisibility(View.VISIBLE);
latLatitude = data.getDoubleExtra("latitude", 0);
......
......@@ -3,4 +3,6 @@
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@color/transparent</item>
</style>
</resources>
\ No newline at end of file
......@@ -47,8 +47,7 @@ dependencies {
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(':jcvideoplayer-lib')
implementation files('libs/ormlite-android-4.48.jar')
implementation files('libs/ormlite-core-4.48.jar')
api files('libs/android-async-http-1.4.5.jar')
implementation 'com.android.support:recyclerview-v7:28.0.0'
// smack
......
......@@ -20,13 +20,16 @@ android {
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
}
......@@ -41,27 +44,27 @@ android {
pro {
}
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
api 'com.jakewharton:butterknife:9.0.0-rc1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
implementation 'com.alibaba:fastjson:1.2.21'
api project(':RvWrapper')
api project(':component_resource')
api project(':component_utils')
api project(':plugin_opengl')
api project(':plugin_imcamera')
api project(':jcvideoplayer-lib')
implementation files('libs/fastjson-1.2.40.jar')
implementation files('libs/ormlite-android-4.48.jar')
implementation files('libs/ormlite-core-4.48.jar')
// 视频缓存 + 视频处理
implementation 'com.danikula:videocache:2.7.1'
implementation 'com.github.yangjie10930:EpMedia:v0.9.5'
......
......@@ -6,7 +6,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
<activity android:name=".activity.RecordxActivity"></activity>
<activity android:name=".activity.SelectMusicActivity"></activity>
<activity android:name=".activity.TriListActivity" />
<activity android:name=".activity.PreviewxActivity" />
<activity android:name=".activity.RecordxActivity" />
</application>
</manifest>
\ No newline at end of file
package com.xxfc.discovery.other;
package com.xxrv.video.activity;
import android.content.Context;
import android.content.Intent;
......@@ -14,12 +14,11 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.xxfc.discovery.R;
import com.xxfc.discovery.R2;
import com.xxfc.discovery.adapter.DiscoveryVideoSelectAdapter;
import com.xxfc.discovery.bean.DiscoveryRecommendBean;
import com.xxfc.discovery.bean.VideoFile;
import com.xxfc.discovery.presenter.DiscoveryPresenter;
import com.xxrv.video.R;
import com.xxrv.video.R2;
import com.xxrv.video.adapter.DiscoveryVideoSelectAdapter;
import com.xxrv.video.bean.circle.VideoFile;
import com.xxrv.video.presenter.VideoPresenter;
import java.io.File;
import java.util.ArrayList;
......@@ -30,7 +29,7 @@ import butterknife.BindView;
/**
* 视频选择
*/
public class SelectVideoActivity extends BaseStatusActivity<DiscoveryPresenter> {
public class SelectVideoActivity extends BaseStatusActivity<VideoPresenter> {
@BindView(R2.id.rv_video_content)
......
package com.xxrv.video.activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PagerSnapHelper;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import com.alibaba.fastjson.JSON;
import com.danikula.videocache.HttpProxyCacheServer;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.xxrv.video.R;
import com.xxrv.video.R2;
import com.xxrv.video.api.VideoApi;
import com.xxrv.video.base.BaseRecAdapter;
import com.xxrv.video.base.BaseRecViewHolder;
import com.xxrv.video.base.Proxy;
import com.xxrv.video.bean.circle.DiscoveryVideoBean;
import com.xxrv.video.dialog.SelectMusicDialog;
import com.xxrv.video.presenter.VideoPresenter;
import com.xxrv.video.weight.JcvTrillVideo;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import butterknife.BindView;
import fm.jiecao.jcvideoplayer_lib.JCMediaManager;
import fm.jiecao.jcvideoplayer_lib.VideotillManager;
public class TriListActivity extends BaseStatusActivity<VideoPresenter> {
@BindView(R2.id.rv_pager)
RecyclerView mPager;
private PagerSnapHelper snapHelper;
private LinearLayoutManager layoutManager;
private ListVideoAdapter videoAdapter;
private List<DiscoveryVideoBean.DataBeanX.DataBean> urlList;
private int position = -1;
private boolean isLoad;
private int pagerIndex;
boolean shareBack;
Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
videoAdapter.notifyDataSetChanged();
layoutManager.scrollToPosition(position);
return true;
}
});
public static Intent getIntent(Context context, int position, int page, List<DiscoveryVideoBean.DataBeanX.DataBean> data) {
return new Intent(context, TriListActivity.class)
.putExtra("position", position)
.putExtra("page", page)
.putExtra("data", JSON.toJSONString(data));
}
@Override
protected int setLayout() {
return R.layout.activity_tri_list;
}
@Override
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
showTitle(false);
position = intent.getIntExtra("position", 0);
pagerIndex = intent.getIntExtra("page", 0);
String data = intent.getStringExtra("data");
urlList = JSON.parseArray(data, DiscoveryVideoBean.DataBeanX.DataBean.class);
snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(mPager);
videoAdapter = new ListVideoAdapter(urlList);
layoutManager = new LinearLayoutManager(this);
mPager.setLayoutManager(layoutManager);
mPager.setAdapter(videoAdapter);
layoutManager.scrollToPosition(position);
mPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
private int position = -1;
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
int cur = layoutManager.findFirstVisibleItemPosition();
if (cur != position) {
position = cur;
// TrillStatisticsHelper.play(mContext, coreManager, urlList.get(cur)); //观看数量统计
}
}
});
addListener();
}
@Override
public void onShowResult(int requestType, BaseBean result) {
switch (requestType) {
case 1:
processData((DiscoveryVideoBean) result);
break;
}
}
private void processData(DiscoveryVideoBean bean) {
isLoad = false;
if (bean.getData() != null && bean.getData().getList() != null && bean.getData().getList().size() > 0) {
urlList.addAll(bean.getData().getList());
Log.e("xuan", "onResponse: " + urlList.size());
videoAdapter.notifyDataSetChanged();
layoutManager.scrollToPosition(position);
}
}
private void addListener() {
mPager.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE://停止滚动
if (urlList == null || urlList.size() == 0) {
return;
}
View view = snapHelper.findSnapView(layoutManager);
RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view);
position = recyclerView.getChildLayoutPosition(view);
if (viewHolder != null && viewHolder instanceof VideoViewHolder) {
JcvTrillVideo video = ((VideoViewHolder) viewHolder).mp_video;
// Log.e("xuan", position + " : 滚动到: " + video.getCurrState());
video.startVideo();
}
if (urlList.size() > position + 1) {
Log.e("xuan", "onScrollStateChanged: " + (position + 1) + ", size " + urlList.size());
HttpProxyCacheServer proxy = Proxy.getInstance().getProxy(TriListActivity.this);
proxy.getProxyUrl(urlList.get(position + 1).getFirstVideo());
}
if (!isLoad && position > urlList.size() - 4) {
pagerIndex++;
loadData();
}
break;
case RecyclerView.SCROLL_STATE_DRAGGING://拖动
break;
case RecyclerView.SCROLL_STATE_SETTLING://惯性滑动
break;
}
}
});
}
@Override
public void onPause() {
super.onPause();
VideotillManager.instance().pause();
}
@Override
public void onResume() {
super.onResume();
Log.e("xuan", "onResume: " + shareBack);
if (!shareBack) {
VideotillManager.instance().play();
} else {
VideotillManager.instance().releaseVideo();
JCMediaManager.instance().releaseMediaPlayer();
handler.sendEmptyMessageDelayed(1, 500);
}
shareBack = false;
}
@Override
public void onDestroy() {
super.onDestroy();
JCMediaManager.addOnJcvdListener(null);
VideotillManager.instance().releaseVideo();
}
class ListVideoAdapter extends BaseRecAdapter<DiscoveryVideoBean.DataBeanX.DataBean, VideoViewHolder> {
public ListVideoAdapter(List<DiscoveryVideoBean.DataBeanX.DataBean> list) {
super(list);
}
@Override
public void onHolder(VideoViewHolder holder, DiscoveryVideoBean.DataBeanX.DataBean bean, int position) {
ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
holder.mp_video.updateDatas(bean, "", "");
holder.mp_video.onShareListener(TriListActivity.this);
holder.mp_video.setPosiont(position);
Log.e("xuan", "onHolder: " + position + " ,, " + TriListActivity.this.position);
if (position == TriListActivity.this.position) {
holder.mp_video.startVideo();
}
}
@Override
public VideoViewHolder onCreateHolder() {
return new VideoViewHolder(getViewByRes(R.layout.item_trill));
}
}
public class VideoViewHolder extends BaseRecViewHolder {
public View rootView;
public JcvTrillVideo mp_video;
public VideoViewHolder(View rootView) {
super(rootView);
this.rootView = rootView;
this.mp_video = rootView.findViewById(R.id.mp_video);
}
}
private void loadData() {
isLoad = true;
Map<String, Object> map = new LinkedHashMap<>();
map.put("page", pagerIndex + "");
map.put("type", 4);
mPresenter.postData(1, VideoApi.DISCOVERY_UNAUTH_LIST, DiscoveryVideoBean.class, map, pagerIndex == 1 ? true : false);
}
}
package com.xxfc.discovery.adapter;
package com.xxrv.video.adapter;
import android.widget.ImageView;
......@@ -6,9 +6,8 @@ import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;
import com.ruiwenliu.wrapper.util.glide.GlideManager;
import com.rv.component.utils.DateUtils;
import com.xxfc.discovery.R;
import com.xxfc.discovery.bean.DiscoveryCommentBean;
import com.xxfc.discovery.bean.VideoFile;
import com.xxrv.video.R;
import com.xxrv.video.bean.circle.VideoFile;
/**
* 短视频选择
......
package com.xxrv.video.api;
import com.frame.rv.config.RvFrameConfig;
public interface VideoApi extends RvFrameConfig {
//获取拍拍、短视频请求列表
String DISCOVERY_UNAUTH_LIST = HOST + "/api/im/msg/app/unauth/list";
//im登录
String DISCOVERY_IM_LOGIN = HOST + "/api/auth/jwt/imi/login";
}
......@@ -23,6 +23,9 @@ import com.xxrv.video.R;
import com.xxrv.video.bean.circle.PublicMessage;
import com.xxrv.video.bean.circle.message.ChatMessage;
import com.xxrv.video.util.FileUtils;
import com.xxrv.video.util.downloader.DownloadListener;
import com.xxrv.video.util.downloader.Downloader;
import com.xxrv.video.util.downloader.FailReason;
import java.io.File;
import static com.xxrv.video.audio_x.VoiceManager.STATE_PLAY;
......
package com.xxrv.video.base;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.xxrv.video.dialog.SelectMusicDialog;
import java.util.ArrayList;
import java.util.List;
/**
* Created by ch
* on 2017/12/19.14:24
* 作用:
*/
public abstract class BaseRecAdapter<T, K extends BaseRecViewHolder> extends RecyclerView.Adapter<K> {
public Context context;
private List<T> list;
private onItemClickListener itemClickListener;
private OnItemLongClickListener itemLongClickListener;
public BaseRecAdapter(List<T> list) {
this.list = list;
}
public OnItemLongClickListener getItemLongClickListener() {
return itemLongClickListener;
}
public void setItemLongClickListener(OnItemLongClickListener itemLongClickListener) {
this.itemLongClickListener = itemLongClickListener;
}
public onItemClickListener getItemClickListener() {
return itemClickListener;
}
public void setItemClickListener(onItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
@Override
public K onCreateViewHolder(ViewGroup parent, int viewType) {
context = parent.getContext();
K holder = onCreateHolder();
//绑定listener
bindListener(holder);
return holder;
}
@Override
public void onBindViewHolder(K holder, int position) {
onHolder(holder, list.get(position), position);
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
/**
* 填充数据
*
* @param holder
* @param position
*/
public abstract void onHolder(K holder, T bean, int position);
public abstract K onCreateHolder();
/**
* 通过资源res获得view
*
* @param res
* @return
*/
public View getViewByRes(int res) {
return LayoutInflater.from(context).inflate(res, null);
}
/**
* 通过资源res获得view
*
* @param res
* @return
*/
public View getViewByRes(int res, ViewGroup prent) {
return LayoutInflater.from(context).inflate(res, prent);
}
/**
* 绑定事件
*
* @param holder
*/
private void bindListener(final K holder) {
if (holder == null) {
return;
}
View itemView = holder.itemView;
if (itemView == null) {
return;
}
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
itemView.setLayoutParams(params);
if (getItemClickListener() != null) {
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getItemClickListener().onItemClick(BaseRecAdapter.this, v, holder.getLayoutPosition());
}
});
}
if (getItemLongClickListener() != null) {
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return getItemLongClickListener().onItemLongClick(BaseRecAdapter.this, v, holder.getLayoutPosition());
}
});
}
}
public void setNewData(List<T> lt) {
if (lt == null) {
lt = new ArrayList<T>();
}
list = lt;
notifyDataSetChanged();
}
public List<T> getData() {
return list;
}
public interface onItemClickListener {
void onItemClick(BaseRecAdapter adapter, View view, int position);
}
public interface OnItemLongClickListener {
boolean onItemLongClick(BaseRecAdapter adapter, View view, int position);
}
}
package com.xxrv.video.base;
import android.text.TextUtils;
import com.danikula.videocache.ProxyCacheUtils;
import com.danikula.videocache.file.FileNameGenerator;
/**
* 作者: ch
* 时间: 2018/10/11 0011-上午 10:12
* 描述: 自定义缓存文件名
* 来源:
*/
public class MyFileNameGenerator implements FileNameGenerator {
private static final int MAX_EXTENSION_LENGTH = 4;
@Override
public String generate(String url) {
String extension = getExtension(url);
int dotIndex = url.lastIndexOf('.');
if (url.length() > 18 && dotIndex > 18) {
return url.substring(dotIndex - 18);
}
String name = ProxyCacheUtils.computeMD5(url);
return TextUtils.isEmpty(extension) ? name : name + "." + extension;
}
private String getExtension(String url) {
int dotIndex = url.lastIndexOf('.');
int slashIndex = url.lastIndexOf('/');
return dotIndex != -1 && dotIndex > slashIndex && dotIndex + 2 + MAX_EXTENSION_LENGTH > url.length() ?
url.substring(dotIndex + 1, url.length()) : "";
}
}
package com.xxrv.video.base;
import android.content.Context;
import com.danikula.videocache.HttpProxyCacheServer;
public class Proxy {
private static Proxy instance = null;
public static <T> Proxy getInstance() {
if (instance == null) {
synchronized (Proxy.class) {
if (instance == null) {
instance = new Proxy();
}
}
}
return instance;
}
// 抖音模块缓存
private HttpProxyCacheServer proxy;
public HttpProxyCacheServer getProxy(Context context) {
return proxy == null ? (proxy = newProxy(context)) : proxy;
}
private HttpProxyCacheServer newProxy(Context context) {
return new HttpProxyCacheServer.Builder(context)
.maxCacheSize(1024 * 1024 * 1024) // 1 Gb for cache
.fileNameGenerator(new MyFileNameGenerator()).build();
}
}
package com.xxrv.video.bean.circle;
import com.alibaba.fastjson.JSONObject;
public class MusicInfo {
public String cover; // 封面图地址
public long length; // 音乐长度
public String name; // 音乐名称
public String nikeName; // 创作人
public String path; // 音乐地址
public int state; // 状态 0未下载 1,播放中,2,下载中,3暂停中
public int useCount;
public String id;
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public long getLength() {
return length;
}
public void setLength(long length) {
this.length = length;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNikeName() {
return nikeName;
}
public void setNikeName(String nikeName) {
this.nikeName = nikeName;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getUseCount() {
return useCount;
}
public void setUseCount(int useCount) {
this.useCount = useCount;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void parseData(JSONObject data) {
this.cover = data.getString("cover");
this.path = data.getString("path");
this.name = data.getString("name");
this.nikeName = data.getString("nikeName");
this.length = data.getInteger("length");
}
public void appendDown(String mDown) {
this.path = mDown + this.path;
}
}
package com.xxrv.video.bean.circle;
import com.ruiwenliu.wrapper.base.BaseBean;
public class VideoIMTokenBean extends BaseBean {
private String data;
private boolean rel;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
......@@ -555,7 +555,7 @@ public class ChatMessage extends XmppMessage implements Parcelable {
return toJsonObject(messageKey).toString();
}
@NotNull
public JSONObject toJsonObject(@Nullable String messageKey) {
JSONObject object = new JSONObject();
object.put("type", this.type);
......
package com.xxrv.video.dialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.xxrv.video.R;
import com.xxrv.video.util.ScreenUtil;
import com.xxrv.video.weight.Xcoverbar;
/**
* 抖音封面选择模块
*/
public class SelectCoverDialog extends Dialog implements View.OnClickListener {
private Context mContext;
private String musicListUrl;
private Xcoverbar mCoverBar;
private Xcoverbar.OnChangeListener mListener;
public SelectCoverDialog(Context context, Xcoverbar.OnChangeListener listener) {
super(context, R.style.TrillDialog);
this.mContext = context;
mListener = listener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_trill_cover);
setCanceledOnTouchOutside(true);
initView();
}
private void initView() {
findViewById(R.id.iv_close).setOnClickListener(this);
findViewById(R.id.iv_select).setOnClickListener(this);
mCoverBar = findViewById(R.id.xcover_bar);
mCoverBar.addOnChangeListener(new Xcoverbar.OnChangeListener() {
@Override
public void change(String curr) {
musicListUrl = curr;
if (mListener != null) {
mListener.change(curr);
}
}
@Override
public void confirm(String curr) {
}
@Override
public void cancel() {
}
});
Window o = getWindow();
WindowManager.LayoutParams lp = o.getAttributes();
lp.width = ScreenUtil.getScreenWidth(getContext());
o.setAttributes(lp);
this.getWindow().setGravity(Gravity.BOTTOM);
this.getWindow().setWindowAnimations(R.style.BottomDialog_Animation);
}
@Override
public void onClick(View v) {
hideCover(v.getId() == R.id.iv_select);
}
public void show(String str) {
super.show();
mCoverBar.setCoverBackground(str);
}
public void hideCover(boolean sure) {
super.dismiss();
if (mListener != null) {
if (sure) {
mListener.confirm(musicListUrl);
} else {
mListener.cancel();
}
}
}
@Override
public void dismiss() {
hideCover(false);
}
}
package com.xxrv.video.dialog;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.ImageView;
import com.xxrv.video.R;
/**
* 生活圈 | 短视频模块 评论&回复 输入框
*/
public class TrillCommentInputDialog2 extends Dialog {
private EditText mEditText;
private ImageView mImageView;
private String mReplyStr;
private OnSendCommentListener mOnSendCommentListener;
public TrillCommentInputDialog2(Context context, String text, OnSendCommentListener onSendCommentListener) {
super(context, R.style.BottomDialog);
this.mReplyStr = text;
this.mOnSendCommentListener = onSendCommentListener;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.a_dialog_for_trill_comment_input);
setCanceledOnTouchOutside(true);
initView();
}
public void initView() {
mImageView = findViewById(R.id.send_iv);
mEditText = findViewById(R.id.comment_et);
if (!TextUtils.isEmpty(mReplyStr)) {
mEditText.setHint(mReplyStr);
}
mImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String mCommentStr = mEditText.getText().toString();
if (TextUtils.isEmpty(mCommentStr)) {
return;
}
if (mOnSendCommentListener != null) {
dismiss();
mOnSendCommentListener.sendComment(mCommentStr);
}
}
});
mEditText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (!TextUtils.isEmpty(mEditText.getText().toString())) {
mImageView.setImageResource(R.drawable.ic_tiktok_send_ing);
} else {
mImageView.setImageResource(R.drawable.ic_tiktok_send_nor);
}
}
});
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
window.setAttributes(params);
window.setGravity(Gravity.BOTTOM);
// window.setWindowAnimations(R.style.BottomDialog_Animation);
}
public interface OnSendCommentListener {
void sendComment(String str);
}
}
......@@ -5,7 +5,6 @@ import com.ruiwenliu.wrapper.presenter.MvpPresenter;
public class VideoPresenter extends MvpPresenter {
@Override
/**
* 域名地址
......
package com.xxrv.video.util;
import android.os.Handler;
import android.os.Looper;
import java.lang.ref.WeakReference;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 封装异步操作,模仿kotlin anko-common,
* https://github.com/Kotlin/anko/blob/master/anko/library/static/commons/src/main/java/Async.kt
* <p>
* doAsync用于线程交互,切到子线程做一些操作后再切到主线程,
* forceAsync用于将一些只能放在子线程的操作放在子线程,同时阻塞主线程等子线程返回值,
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public class AsyncUtils {
public static ExecutorService backgroundExecutor = Executors.newScheduledThreadPool(
2 * Runtime.getRuntime().availableProcessors());
private static Function<Throwable> crashLogger;
private AsyncUtils() {
}
public static <T> void postDelayed(final T t, final Function<T> block, long delay) {
ContextHelper.handler.postDelayed(() -> {
try {
block.apply(t);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}, delay);
}
public static <T> void runOnUiThread(final T t, final Function<T> block) {
if (Looper.getMainLooper().equals(Looper.myLooper())) {
try {
block.apply(t);
} catch (Exception e) {
throw new IllegalStateException(e);
}
} else {
ContextHelper.handler.post(() -> {
try {
block.apply(t);
} catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
}
public static <T> Future<?> doAsync(
T t,
Function<AsyncContext<T>> task
) {
return doAsync(t, crashLogger, backgroundExecutor, task);
}
public static <T> Future<?> doAsync(
T t,
ExecutorService executorService,
Function<AsyncContext<T>> task
) {
return doAsync(t, crashLogger, executorService, task);
}
public static <T> Future<?> doAsync(
T t,
Function<Throwable> exceptionHandler,
Function<AsyncContext<T>> task
) {
return doAsync(t, exceptionHandler, backgroundExecutor, task);
}
public static <T> Future<?> doAsync(
T t,
final Function<Throwable> exceptionHandler,
ExecutorService executorService,
final Function<AsyncContext<T>> task
) {
final AsyncContext<T> context = new AsyncContext<>(new WeakReference<>(t));
return executorService.submit(() -> {
try {
task.apply(context);
} catch (Throwable t1) {
if (exceptionHandler != null) {
try {
exceptionHandler.apply(t1);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
}
});
}
/**
* 强行把操作放在子线程,主线程等待该子线程返回,
*/
public static <R> R forceAsync(
final Callable<R> block
) {
return forceAsync(crashLogger, backgroundExecutor, block);
}
/**
* 强行把操作放在子线程,主线程等待该子线程返回,
*/
public static <R> R forceAsync(
final Function<Throwable> exceptionHandler,
ExecutorService executorService,
final Callable<R> block
) {
Future<R> future = executorService.submit(() -> {
try {
return block.call();
} catch (Throwable t) {
if (exceptionHandler != null) {
exceptionHandler.apply(t);
}
throw t;
}
});
try {
return future.get();
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
public interface Function0 {
void apply() throws Exception;
}
public interface Function<T> {
void apply(T t) throws Exception;
}
public interface FunctionResult<T, R> {
R apply(T t) throws Exception;
}
private static class ContextHelper {
private static final Handler handler = new Handler(Looper.getMainLooper());
private ContextHelper() {
}
}
public static class AsyncContext<T> {
public WeakReference<T> weakRef;
public AsyncContext(WeakReference<T> weakRef) {
this.weakRef = weakRef;
}
public T getRef() {
return weakRef.get();
}
public boolean postDelayed(final Function<T> block, long delay) {
final T ref = weakRef.get();
if (ref == null) {
return false;
}
ContextHelper.handler.postDelayed(() -> {
try {
block.apply(ref);
} catch (Exception e) {
throw new IllegalStateException(e);
}
}, delay);
return true;
}
/**
* @return 方法块没执行就返回false, 也就是弱引用被回收的情况,
*/
public boolean uiThread(final Function<T> block) {
final T ref = weakRef.get();
if (ref == null) {
return false;
}
if (Looper.getMainLooper().equals(Looper.myLooper())) {
try {
block.apply(ref);
} catch (Exception e) {
throw new IllegalStateException(e);
}
} else {
ContextHelper.handler.post(() -> {
try {
block.apply(ref);
} catch (Exception e) {
throw new IllegalStateException(e);
}
});
}
return true;
}
}
}
......@@ -24,7 +24,7 @@ public class Parameter {
return joinSortedMap(treeMap);
}
@NotNull
public static String joinSortedMap(TreeMap<String, String> treeMap) {
StringBuilder sb = new StringBuilder();
for (String value : treeMap.values()) {
......
package com.xxrv.video.util;
import android.view.View;
import android.widget.TextView;
/**
* Created by Administrator on 2017/10/26.
*/
public class UiUtils {
private static final int MIN_CLICK_DELAY_TIME = 600;
private static long lastClickTime;
private static int clickedView;
public static void updateNum(TextView numTv, int unReadNum) {
if (numTv == null) {
return;
}
if (unReadNum < 1) {
numTv.setText("");
numTv.setVisibility(View.INVISIBLE);
} else if (unReadNum > 99) {
numTv.setText("99+");
numTv.setVisibility(View.VISIBLE);
} else {
numTv.setText(String.valueOf(unReadNum));
numTv.setVisibility(View.VISIBLE);
}
}
/**
* @deprecated {@link UiUtils#isNormalClick(View)}
*/
@Deprecated
public static boolean isNormalClick() {
boolean isNormal = false;
long currentTime = System.currentTimeMillis();
if ((currentTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
isNormal = true;
}
lastClickTime = currentTime;
return isNormal;
}
public static boolean isNormalClick(View view) {
// hashCode确保同一个view计算出来是一样的,不同view也几乎不会遇到相同hashCode的情况,
long currentTime = System.currentTimeMillis();
if (clickedView != view.hashCode()) {
// 点击不同的view,不限制时间间隔,
clickedView = view.hashCode();
lastClickTime = currentTime;
return true;
}
// 同一个view多次点击,限制连续点击时间,
clickedView = view.hashCode();
boolean isNormal = false;
if ((currentTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
isNormal = true;
}
lastClickTime = currentTime;
return isNormal;
}
}
package com.xxrv.video.util.downloader;
import java.util.concurrent.locks.ReentrantLock;
public final class DownLoadingInfo {
final String uri;
final ViewAware viewAware;
final ReentrantLock loadFromUriLock;
final DownloadListener listener;
final DownloadProgressListener progressListener;
public DownLoadingInfo(String uri, ViewAware viewAware, ReentrantLock loadFromUriLock, DownloadListener listener, DownloadProgressListener progressListener) {
this.uri = uri;
this.viewAware = viewAware;
this.loadFromUriLock = loadFromUriLock;
this.listener = listener;
this.progressListener = progressListener;
}
}
/*******************************************************************************
* Copyright 2011-2013 Sergey Tarasevich
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.xxrv.video.util.downloader;
import android.view.View;
public interface DownloadListener {
void onStarted(String uri, View view);
void onFailed(String uri, FailReason failReason, View view);
void onComplete(String uri, String filePath, View view);
void onCancelled(String uri, View view);
}
package com.xxrv.video.util.downloader;
import android.view.View;
public interface DownloadProgressListener {
void onProgressUpdate(String imageUri, View view, int current, int total);
}
package com.xxrv.video.util.downloader;
public class FailReason {
private final FailType type;
private final Throwable cause;
public FailReason(FailType type, Throwable cause) {
this.type = type;
this.cause = cause;
}
/**
* @return {@linkplain FailType Fail type}
*/
public FailType getType() {
return type;
}
/**
* @return Thrown exception/error, can be <b>null</b>
*/
public Throwable getCause() {
return cause;
}
/**
* Presents type of fail while image loading
*/
public static enum FailType {
/**
* Input/output error. Can be caused by network communication fail or
* error while caching image on file system.
*/
IO_ERROR,
/* URI为空,不可用 */
URI_EMPTY,
/**
* Unknown error was occurred while loading image
*/
UNKNOWN
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="4500"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="-1"
android:toDegrees="359">
</rotate>
</set>
<!-- 抖音模块 光盘旋转效果实现 -->
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment