Commit 2b41a1e7 authored by linfeng's avatar linfeng

bug修复

parent b28eace5
......@@ -41,20 +41,22 @@ public class OkGoUtil {
public static String TOKEN_KEY = "Authorization";
//把Token保存到SP文件中的Key
final private static String SP_KEY_TOKEN = "sp_key_token";
final private static String SP_KEY_TOKEN_TIME = "sp_key_token_time";
final private static String SP_KEY_USERINFO ="userinfo";
final private static String SP_KEY_USERINFO = "userinfo";
public static String getYkId(){
String ykid = "uk_"+ (int)((Math.random()*9+1)*100000);
public static String getYkId() {
String ykid = "uk_" + (int) ((Math.random() * 9 + 1) * 100000);
return ykid;
}
//保存Token
public static void setToken(String token) {
public static void setToken(String token, String time) {
if (application == null) return;
SharedPreferences sp = application.getSharedPreferences(OkGoUtil.class.getSimpleName(), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString(SP_KEY_TOKEN, token);
editor.putString(SP_KEY_TOKEN_TIME, time);
editor.apply();
editor.commit();
}
......@@ -68,11 +70,20 @@ public class OkGoUtil {
return null;
}
//获取Token登录时间
public static String getTime() {
if (application != null) {
SharedPreferences sp = application.getSharedPreferences(OkGoUtil.class.getSimpleName(), Context.MODE_PRIVATE);
return sp.getString(SP_KEY_TOKEN_TIME, null);
}
return null;
}
/**
* 清空Token
*/
public static void clearToken(){
if (application ==null)
public static void clearToken() {
if (application == null)
return;
SharedPreferences sp = application.getSharedPreferences(OkGoUtil.class.getSimpleName(), Context.MODE_PRIVATE);
sp.edit().clear().commit();
......@@ -269,7 +280,7 @@ public class OkGoUtil {
getUrl = getUrl(url, param);
} else {
getUrl = url;
Log.d(OkGoUtil.class.getSimpleName(), "getJson():\n url:" + url );
Log.d(OkGoUtil.class.getSimpleName(), "getJson():\n url:" + url);
}
GetRequest<String> request;
request = OkGo.<String>get(getUrl)
......@@ -327,7 +338,7 @@ public class OkGoUtil {
sb.append(key);
sb.append("=");
sb.append(value);
}catch (Exception e){
} catch (Exception e) {
//忽略
}
}
......
......@@ -8,8 +8,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
flavorDimensions "default"
versionCode 142
versionName "1.4.2"
versionCode 143
versionName "1.4.3"
multiDexEnabled true
ndk {
......
......@@ -29,6 +29,7 @@ import com.ruiwenliu.wrapper.base.BaseActivity;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseWrapperFragment;
import com.ruiwenliu.wrapper.bean.ActBean;
import com.ruiwenliu.wrapper.bean.UpdateTokenBean;
import com.ruiwenliu.wrapper.receiver.NetWorkReceiver;
import com.ruiwenliu.wrapper.statusbar.StatusBarUtil;
import com.ruiwenliu.wrapper.util.listener.SwitchFragment;
......@@ -36,6 +37,7 @@ import com.ruiwenliu.wrapper.weight.CustomScrollViewPager;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.rv.camp.CampFragment;
import com.rv.component.utils.Cookie;
import com.rv.component.utils.DateUtils;
import com.rv.home.rv.module.ApiConfig;
import com.ruiwenliu.wrapper.base.presenter.CommonPresenter;
import com.rv.home.rv.module.ui.main.home.HomeFragment;
......@@ -207,25 +209,43 @@ public class MainActivity extends BaseActivity<CommonPresenter> {
promotionDialog.show();
}
break;
case 3:
case 4:
UpdateTokenBean updateTokenBean = (UpdateTokenBean) result;
if (updateTokenBean != null && !TextUtils.isEmpty(updateTokenBean.getData())) {
OkGoUtil.setToken(updateTokenBean.getData(), DateUtils.getCurDateTime());
}
break;
default:
break;
}
}
/**
* 检查token是否过期
* 设置token时间检测
*/
private void checkToken() {
String time = OkGoUtil.getTime();
if (!TextUtils.isEmpty(time)) {
// if (DateUtils.compareDateDay(DateUtils.getCurDate(), time) > 6) {
if (DateUtils.compareDateSecond(DateUtils.getCurDateTime(), time) > 120) {
getToken();
}
} else {
getToken();
}
}
/**
* 获取新token
*/
private void getToken() {
Map<String, Object> heapmap = new HashMap<>();
Map<String, Object> map = new HashMap<>();
if (!TextUtils.isEmpty(OkGoUtil.getToken())) {
map.put("Authorization", OkGoUtil.getToken());
heapmap.put("Authorization", OkGoUtil.getToken());
map.put("token", OkGoUtil.getToken());
mPresenter.getData(RvFrameConfig.HOST, 3, ApiConfig.HTTP_URL_GET_TOKEN, BaseBean.class, map, heapmap, false);
mPresenter.getData(RvFrameConfig.HOST, 4, ApiConfig.HTTP_URL_GET_TOKEN, UpdateTokenBean.class, map, heapmap, false);
}
}
......@@ -260,6 +280,7 @@ public class MainActivity extends BaseActivity<CommonPresenter> {
setCurrent(TYPE_FOUND);
} else if (id == R.id.rl_mine) {
setCurrent(TYPE_MINE);
checkToken();
}
}
......
......@@ -7,14 +7,20 @@ import android.os.Bundle;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import com.ruiwenliu.wrapper.SPConstance;
import com.ruiwenliu.wrapper.base.BaseActivity;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.util.UtilsManager;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.rv.component.utils.Cookie;
import com.rv.component.utils.DateUtils;
import com.rv.component.utils.LogUtil;
import com.ruiwenliu.wrapper.base.presenter.CommonPresenter;
import com.yuyife.okgo.OkGoUtil;
import java.util.concurrent.TimeUnit;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
......@@ -68,11 +74,10 @@ public class WelcomeActivity extends BaseActivity<CommonPresenter> {
@Override
public void accept(@NonNull Long aLong) {
try {
if (!TextUtils.isEmpty(UtilsManager.getInstance(mActivity).getSPInstance("city_json").getString("token", ""))) {
OkGoUtil.setToken(
UtilsManager.getInstance(mActivity)
.getSPInstance("city_json")
.getString("token", ""));
String token = Cookie.getStringValue(getApplicationContext(), SPConstance.USER_JSON_TOKEN, "");
String tokenTime = Cookie.getStringValue(getApplicationContext(), SPConstance.USER_JSON_TOKE_TIME, "");
if (!TextUtils.isEmpty(token)) {
OkGoUtil.setToken(token, DateUtils.getCurDateTime());
}
} catch (Exception e) {
e.printStackTrace();
......@@ -106,7 +111,7 @@ public class WelcomeActivity extends BaseActivity<CommonPresenter> {
super.onCreate(savedInstanceState);
// this.getWindow().getDecorView().setBackground(null);
if (Build.VERSION.SDK_INT >= 21) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |View.SYSTEM_UI_FLAG_FULLSCREEN);
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN);
}
// if (Build.VERSION.SDK_INT >= 21) {
// View decorView = getWindow().getDecorView();
......
......@@ -15,6 +15,9 @@ public interface RvFrameConstant {
int HTTP_STATE_DATA_ALREADY_EXISTS = 1009;
int HTTP_STATE_NOT_CHECKTOKEN = 10003; //参数不能为空",
int HTTP_STATE_DATA_NOT_CHECKTOKEN =10009; //"token无效",
int HTTP_STATE_TOKEN_EXPIRED =40101; //用户token异常
int HTTP_STATE_TOKEN_EXPIRED_PASS =40001; //用户token异常
int HTTP_STATE_TOKEN_EXPIRED_PASS2 =40301; //用户token异常
/**
* 请求错误类型
*/
......
......@@ -11,4 +11,5 @@ public final class SPConstance {
public static final String USER_JSON_ISCERTIFICATIONSTATUS ="CertificationStatus";
public static final String USER_JSON_USERINFO ="userinfo";
public static final String USER_JSON_CODE = "userCode";
public static final String USER_JSON_TOKE_TIME = "tokentime";
}
......@@ -10,6 +10,7 @@ import android.view.Window;
import com.alibaba.android.arouter.launcher.ARouter;
import com.base.utils.tools.android.NetworkUtil;
import com.frame.base.url.Constance;
import com.ruiwenliu.wrapper.R;
import com.ruiwenliu.wrapper.dialog.LoadingDialog;
import com.ruiwenliu.wrapper.presenter.MvpPresenter;
......@@ -97,6 +98,10 @@ public abstract class BaseActivity<P extends MvpPresenter> extends BaseWrapperAc
}
}
@Override
public void onErrorToken() {
ARouter.getInstance().build(Constance.ACTIVITY_URL_LOGINRV).navigation();
}
protected LoadingDialog createLoadingDialog() {
if (mLoadingDialog == null) {
......
......@@ -36,4 +36,9 @@ public interface BaseView<T extends BaseBean> {
* @param errorMsg
*/
void onShowError(String errorMsg, int errorType);
/**
* token过期或者异常
*/
void onErrorToken();
}
......@@ -12,6 +12,7 @@ import android.widget.Toast;
import com.alibaba.android.arouter.launcher.ARouter;
import com.base.utils.tools.android.NetworkUtil;
import com.frame.base.url.Constance;
import com.ruiwenliu.wrapper.R;
import com.ruiwenliu.wrapper.dialog.LoadingDialog;
import com.ruiwenliu.wrapper.presenter.MvpPresenter;
......@@ -135,6 +136,10 @@ public abstract class BaseWrapperFragment<P extends MvpPresenter> extends Suppor
}
}
@Override
public void onErrorToken() {
ARouter.getInstance().build(Constance.ACTIVITY_URL_LOGINRV).navigation();
}
/**
* @return 布局resourceId
......
package com.ruiwenliu.wrapper.bean;
import com.ruiwenliu.wrapper.base.BaseBean;
public class UpdateTokenBean extends BaseBean {
private String data;
private int code;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
......@@ -63,6 +63,12 @@ public class RxRequestResult<T extends BaseBean, V extends BaseView<T>> extends
case RvFrameConstant.HTTP_STATE_DATA_NOT_CHECKTOKEN:
RxBus.post(new SignOutEvent());
break;
case RvFrameConstant.HTTP_STATE_TOKEN_EXPIRED:
case RvFrameConstant.HTTP_STATE_TOKEN_EXPIRED_PASS:
case RvFrameConstant.HTTP_STATE_TOKEN_EXPIRED_PASS2:
RxBus.post(new SignOutEvent());
baseView.onErrorToken();
break;
default:
baseView.onShowError(bean.message, bean.status);
break;
......@@ -92,36 +98,27 @@ public class RxRequestResult<T extends BaseBean, V extends BaseView<T>> extends
baseView.onHideLoading();
if (e instanceof SocketTimeoutException) {//请求超时
} else if (e instanceof ConnectException) {//网络连接超时
// ToastManager.showShortToast("网络连接超时");
baseView.onShowError("网络连接超时", position);
} else if (e instanceof SSLHandshakeException) {//安全证书异常
// ToastManager.showShortToast("安全证书异常");
baseView.onShowError("安全证书异常", position);
} else if (e instanceof HttpException) {//请求的地址不存在
int code = ((HttpException) e).code();
if (code == 504) {
// ToastManager.showShortToast("网络异常,请检查您的网络状态");
baseView.onShowError("网络异常,请检查您的网络状态", position);
} else if (code == 404) {
// ToastManager.showShortToast("请求的地址不存在");
baseView.onShowError("请求的地址不存在", position);
} else {
// ToastManager.showShortToast("请求失败");
baseView.onShowError("请求失败", position);
}
} else if (e instanceof UnknownHostException) {//域名解析失败
// ToastManager.showShortToast("域名解析失败");
baseView.onShowError("域名解析失败", position);
} else {
// ToastManager.showShortToast("error:" + e.getMessage());
baseView.onShowError("error:" + e.getMessage(), position);
}
} catch (Exception e2) {
e2.printStackTrace();
} finally {
Log.e("OnSuccessAndFaultSub", "error:" + e.getMessage());
// mOnSuccessAndFaultListener.onFault("error:" + e.getMessage());
// dismissProgressDialog();
}
}
......
......@@ -136,4 +136,9 @@ public class ApiConfig {
* 检查token是否有效
*/
public static String HTTP_URL_GET_TOKEN = RvFrameConfig.HOST + "/api/auth/jwt/checkToken";
/**
* 获取新的token
*/
public static String HTTP_URL_GET_TOKEN_REFRESH = RvFrameConfig.HOST + "/api/auth/jwt/refresh";
}
......@@ -16,6 +16,7 @@ import com.ruiwenliu.wrapper.presenter.MvpPresenter;
import com.ruiwenliu.wrapper.util.UtilsManager;
import com.ruiwenliu.wrapper.weight.TitleView;
import com.rv.component.utils.Cookie;
import com.rv.component.utils.DateUtils;
import com.rv.component.utils.LogUtil;
import com.rv.home.R;
import com.rv.home.rv.module.ApiConfig;
......@@ -124,6 +125,8 @@ public abstract class BaseLoginActivity<P extends MvpPresenter> extends BaseStat
Cookie.save(getApplicationContext(), SPConstance.USER_JSON_NAME, registeredBean.getData().getUsername());
Cookie.save(getApplicationContext(), SPConstance.USER_JSON_HEADERURL, registeredBean.getData().getHeaderurl());
Cookie.save(getApplicationContext(), SPConstance.USER_JSON_TOKEN, registeredBean.getToken());
Cookie.save(getApplicationContext(), SPConstance.USER_JSON_TOKE_TIME, DateUtils.getCurDate());
UtilsManager.getInstance(OkGoUtil.application).setSharePreferencesSave(SPConstance.USER_JSON).putString(SPConstance.USER_JSON_CODE, registeredBean.getData().getCode()).commit();
UtilsManager.getInstance(OkGoUtil.application).setSharePreferencesSave(SPConstance.USER_JSON).putString(SPConstance.USER_JSON_NAME, registeredBean.getData().getUsername()).commit();
UtilsManager.getInstance(OkGoUtil.application).setSharePreferencesSave(SPConstance.USER_JSON).putString(SPConstance.USER_JSON_HEADERURL, registeredBean.getData().getHeaderurl()).commit();
......@@ -138,7 +141,7 @@ public abstract class BaseLoginActivity<P extends MvpPresenter> extends BaseStat
headMap.put("Authorization", registeredBean.getToken());
mPresenter.getDataHead(RvFrameConfig.ADMIN_POST, 10, ApiConfig.HTTP_URL_APP_USER_INFO, BeanUserInfo.class, headMap, false);
}
OkGoUtil.setToken(registeredBean.getToken());
OkGoUtil.setToken(registeredBean.getToken(), DateUtils.getCurDateTime());
// switch (RvFrameConfig.RvFrameInfo.TYPE_LOGIN) {
// case 1:
// if ("0".equals(bean.getData().getCertificationStatus())) { //实名认证状态:0-未认证,1-已认证
......
......@@ -8,6 +8,9 @@ import android.support.v7.widget.RecyclerView;
import android.view.View;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
......@@ -25,6 +28,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class DrivingListActivity extends BaseStatusActivity<CommonPresenter> implements BaseQuickAdapter.RequestLoadMoreListener {
@BindView(R2.id.recyclerView)
......@@ -93,6 +98,20 @@ public class DrivingListActivity extends BaseStatusActivity<CommonPresenter> imp
}
}
});
initRxBus();
}
private void initRxBus() {
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onRefresh();
}
});
}
......
......@@ -14,6 +14,7 @@ import android.view.View;
import com.alipay.sdk.app.PayTask;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.frame.base.bus.Observer;
import com.frame.base.bus.PaymentSuccessfulEvent;
import com.frame.base.bus.RxBus;
import com.frame.rv.config.RvFrameConfig;
......@@ -42,6 +43,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
/**
* Created :Auser
......@@ -136,6 +138,18 @@ public class AllOrderFragment extends BaseFragment<CommonPresenter> implements B
}
});
initRxbus();
}
private void initRxbus() {
RxBus.tObservable(PaymentSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<PaymentSuccessfulEvent>(disposable) {
@Override
public void onNext(PaymentSuccessfulEvent event) {
onRefresh();
}
});
}
@Override
......
......@@ -16,6 +16,7 @@ import com.alipay.sdk.app.PayTask;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.frame.base.bus.CancelOrderEvent;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.PaymentSuccessfulEvent;
import com.frame.base.bus.RxBus;
......@@ -48,6 +49,7 @@ import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
/**
* Created :Auser
......@@ -172,6 +174,16 @@ public class ForPaymentFragment extends BaseFragment<CommonPresenter> implements
}
});
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onRefresh();
}
});
}
@Override
......
......@@ -8,6 +8,9 @@ import android.view.View;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseFragment;
......@@ -26,6 +29,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created :Auser
......@@ -86,8 +91,22 @@ public class HaveToTravelFragment extends BaseFragment<CommonPresenter>implement
}
}
});
initRxbus();
}
private void initRxbus() {
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onRefresh();
}
});
}
@Override
protected void loadData(Bundle savedInstanceState) {
......
......@@ -10,6 +10,7 @@ import android.view.View;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.frame.base.bus.CancelOrderEvent;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.PaymentSuccessfulEvent;
import com.frame.base.bus.RxBus;
......@@ -32,6 +33,7 @@ import java.util.Map;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* Created :Auser
......@@ -124,6 +126,14 @@ public class ToTravelFragment extends BaseFragment<CommonPresenter> implements B
}
});
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onRefresh();
}
});
}
......
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorLine"
tools:context=".rv.module.ui.main.home.CarRentalActivity">
<include layout="@layout/common_rv" />
<ImageView
android:id="@+id/iv_top"
android:layout_width="@dimen/size_50"
android:layout_height="@dimen/size_50"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="@dimen/size_30"
android:layout_marginRight="@dimen/size_30"
android:gravity="center"
android:src="@drawable/rv_top"
android:textColor="@color/colorWrite" />
</RelativeLayout>
This diff is collapsed.
......@@ -11,6 +11,9 @@ import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.base.url.Constance;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
......@@ -37,6 +40,8 @@ import java.util.Map;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
/**
* 选择出游人 / 选择出游人
......@@ -76,6 +81,7 @@ public class ChooseAVisitorActivity extends BaseStatusActivity<CommonPresenter>
@Override
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
openType = intent.getIntExtra("openType", 0);
initRxBus();
if (openType != 0) {
adultNumber = intent.getIntExtra("adult_number", 0);
childBumber = intent.getIntExtra("child_number", 0);
......@@ -225,6 +231,18 @@ public class ChooseAVisitorActivity extends BaseStatusActivity<CommonPresenter>
super.finish();
}
private void initRxBus() {
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
getDrivingList();
}
});
}
@Override
protected void loadData(Bundle savedInstanceState, Intent intent) {
super.loadData(savedInstanceState, intent);
......
......@@ -10,6 +10,9 @@ import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.entity.MultiItemEntity;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.base.url.Constance;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
......@@ -28,6 +31,8 @@ import java.util.LinkedHashMap;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
public class CollectionActivity extends BaseStatusActivity<CommonPresenter> implements BaseQuickAdapter.RequestLoadMoreListener {
@BindView(R2.id.recyclerView)
......@@ -51,7 +56,7 @@ public class CollectionActivity extends BaseStatusActivity<CommonPresenter> impl
@Override
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
titleView.setTitle("收藏");
initRxBus();
recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
collectionAdapter = new CollectionAdapter(new ArrayList<MultiItemEntity>());
collectionAdapter.setOnLoadMoreListener(this, recyclerView);
......@@ -61,22 +66,34 @@ public class CollectionActivity extends BaseStatusActivity<CommonPresenter> impl
@Override
public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
CollectionListBean.DataBeanX.DataBean dataBean = (CollectionListBean.DataBeanX.DataBean) adapter.getItem(position);
if ( 2 == dataBean.getType()) {
if (2 == dataBean.getType()) {
ARouter.getInstance()
.build(Constance.ACTIVITY_URL_TRAVELDETAILS)
.withString("id", dataBean.getTypeId())
.withString("name", dataBean.getName())
.withString("content", dataBean.getUnit())
.withString("url", dataBean.getCover())
.withDouble("price",dataBean.getPrice())
.withDouble("price", dataBean.getPrice())
.navigation();
}else if (1 == dataBean.getType()){
} else if (1 == dataBean.getType()) {
}
}
});
}
private void initRxBus() {
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onRefresh();
}
});
}
@Override
protected void loadData(Bundle savedInstanceState, Intent intent) {
super.loadData(savedInstanceState, intent);
......@@ -118,7 +135,7 @@ public class CollectionActivity extends BaseStatusActivity<CommonPresenter> impl
headMap.put("Authorization", OkGoUtil.getToken());
Map<String, Object> map = new LinkedHashMap<>();
map.put("page", page);
mPresenter.getData(RvFrameConfig.ADMIN_POST, 0, ApiConfig.HTTP_URL_COLLECTONLIST, CollectionListBean.class, map,headMap, page == 1 ? true : false);
mPresenter.getData(RvFrameConfig.ADMIN_POST, 0, ApiConfig.HTTP_URL_COLLECTONLIST, CollectionListBean.class, map, headMap, page == 1 ? true : false);
}
......
......@@ -10,6 +10,9 @@ import android.view.View;
import com.alibaba.android.arouter.launcher.ARouter;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.frame.base.url.Constance;
import com.frame.rv.config.RvFrameConfig;
import com.ruiwenliu.wrapper.base.BaseBean;
......@@ -29,6 +32,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import butterknife.BindView;
import io.reactivex.schedulers.Schedulers;
/**
* 我的发布
......@@ -58,7 +62,7 @@ public class MyReleaseActivity extends BaseStatusActivity<CommonPresenter> imple
titleView.setTitle("我的发布");
mSimpleRefreshLayout.setHeaderView(new SimpleRefreshView(mActivity));
mSimpleRefreshLayout.setOnSimpleRefreshListener(this);
initRxBus();
mAdapter = new MyReleasePatAdapter();
final StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
......@@ -120,6 +124,19 @@ public class MyReleaseActivity extends BaseStatusActivity<CommonPresenter> imple
}, rvContent);
}
private void initRxBus() {
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(Schedulers.newThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
onFresh();
}
});
}
@Override
protected void loadData(Bundle savedInstanceState, Intent intent) {
super.loadData(savedInstanceState, intent);
......
......@@ -10,6 +10,9 @@ import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.RxBus;
import com.ruiwenliu.wrapper.base.BaseBean;
import com.ruiwenliu.wrapper.base.BaseStatusActivity;
import com.ruiwenliu.wrapper.util.UtilsManager;
......@@ -31,6 +34,7 @@ import java.util.Map;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import io.reactivex.schedulers.Schedulers;
/**
* 设置
......@@ -59,6 +63,7 @@ public class SettingActivity extends BaseStatusActivity<CommonPresenter> {
isShowLoadingError = false;
}
@Override
protected void loadData(Bundle savedInstanceState, Intent intent) {
super.loadData(savedInstanceState, intent);
......
......@@ -22,7 +22,6 @@ public class TravelBookingDeparturetimeAdapter extends BaseQuickAdapter<BeanTour
protected void convert(BaseViewHolder helper, BeanTourDetailData.DataBeanX.TourDepartTimeVo item) {
String time = item.getStartTime() + getWeek(item.getStartWeek()) + "~" + item.getEndTime() + getWeek(item.getEndWeek());
helper.setText(R.id.tv_time, time);
if ("0".equals(item.getOverdue())) {
if (selectPosition == mData.indexOf(item)) {
......@@ -33,6 +32,7 @@ public class TravelBookingDeparturetimeAdapter extends BaseQuickAdapter<BeanTour
helper.setTextColor(R.id.tv_time, ContextCompat.getColor(mContext, R.color.colorMain));
} else {
helper.setTextColor(R.id.tv_time, ContextCompat.getColor(mContext, R.color.textGray));
helper.getView(R.id.iv_time_select).setSelected(false);
}
}
......
......@@ -140,7 +140,7 @@ public class TravelDetailsActivity extends BaseStatusActivity<TourismPresenter>
protected void initView(Bundle savedInstanceState, TitleView titleView, Intent intent) {
showTitle(false);
tvTitleCenter.setText("旅游详情");
webUrl = TourismApi.TRAVEL_DETAILS + "?id=" + id;
webUrl = TourismApi.TRAVEL_DETAILS + "?id=" + id + "?v=1";
initWeb();
initRxbus();
if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(url)) {
......@@ -506,8 +506,13 @@ public class TravelDetailsActivity extends BaseStatusActivity<TourismPresenter>
@JavascriptInterface
public void showDialog() {
mWebView.post(new Runnable() {
@Override
public void run() {
travelBooking();
}
});
}
@JavascriptInterface
public void showButton() {
......
......@@ -17,6 +17,8 @@ import android.widget.TextView;
import com.alibaba.android.arouter.launcher.ARouter;
import com.alipay.sdk.app.EnvUtils;
import com.base.utils.ui.image.round.RoundImageView;
import com.frame.base.bus.LoginSuccessfulEvent;
import com.frame.base.bus.Observer;
import com.frame.base.bus.PaymentFailedEvent;
import com.frame.base.bus.PaymentSuccessfulEvent;
import com.frame.base.bus.RxBus;
......@@ -50,6 +52,7 @@ import java.util.Map;
import butterknife.BindView;
import butterknife.OnClick;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
......@@ -157,6 +160,16 @@ public class MemberCenterActivity extends BaseStatusActivity<MemberPresenter> {
}
});
Log.e("xxxxxxxxxxxxxx", disposableSuc == disposableFail ? "true" : "false");
RxBus.tObservable(LoginSuccessfulEvent.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<LoginSuccessfulEvent>(disposable) {
@Override
public void onNext(LoginSuccessfulEvent event) {
getUserData();
getMemberData();
}
});
}
@Override
......@@ -238,7 +251,7 @@ public class MemberCenterActivity extends BaseStatusActivity<MemberPresenter> {
*/
private boolean isLogin() {
if (TextUtils.isEmpty(OkGoUtil.getToken())) {
startActivityForResult(LoginRvActivity.getIntent(MemberCenterActivity.this,0), REQUEST_LOGIN);
startActivityForResult(LoginRvActivity.getIntent(MemberCenterActivity.this, 0), REQUEST_LOGIN);
return false;
}
return true;
......
......@@ -51,7 +51,6 @@
android:id="@+id/ll_webview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ll_item_title"
android:layout_marginLeft="@dimen/size_15"
android:layout_marginTop="@dimen/size_15"
android:layout_marginRight="@dimen/size_15"
......
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
}
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.dueeeke.videoplayer">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
package com.dueeeke.videoplayer.controller;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.support.annotation.AttrRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import com.dueeeke.videoplayer.R;
import com.dueeeke.videoplayer.player.VideoView;
import com.dueeeke.videoplayer.player.VideoViewManager;
import com.dueeeke.videoplayer.util.PlayerUtils;
import com.dueeeke.videoplayer.widget.StatusView;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Formatter;
import java.util.Locale;
/**
* 控制器基类
* Created by Devlin_n on 2017/4/12.
*/
public abstract class BaseVideoController extends FrameLayout {
protected View mControllerView;//控制器视图
protected MediaPlayerControl mMediaPlayer;//播放器
protected boolean mShowing;//控制器是否处于显示状态
protected boolean mIsLocked;
protected int mDefaultTimeout = 4000;
private StringBuilder mFormatBuilder;
private Formatter mFormatter;
protected int mCurrentPlayState;
protected StatusView mStatusView;
public BaseVideoController(@NonNull Context context) {
this(context, null);
}
public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BaseVideoController(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
protected void initView() {
mControllerView = LayoutInflater.from(getContext()).inflate(getLayoutId(), this);
mFormatBuilder = new StringBuilder();
mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
mStatusView = new StatusView(getContext());
setClickable(true);
setFocusable(true);
}
/**
* 设置控制器布局文件,子类必须实现
*/
protected abstract int getLayoutId();
/**
* 显示
*/
public void show() {
}
/**
* 隐藏
*/
public void hide() {
}
public void setPlayState(int playState) {
mCurrentPlayState = playState;
hideStatusView();
if (playState == VideoView.STATE_ERROR) {
mStatusView.setMessage(getResources().getString(R.string.dkplayer_error_message));
mStatusView.setButtonTextAndAction(getResources().getString(R.string.dkplayer_retry), new OnClickListener() {
@Override
public void onClick(View v) {
hideStatusView();
mMediaPlayer.replay(false);
}
});
this.addView(mStatusView, 0);
}
}
public void showStatusView() {
this.removeView(mStatusView);
mStatusView.setMessage(getResources().getString(R.string.dkplayer_wifi_tip));
mStatusView.setButtonTextAndAction(getResources().getString(R.string.dkplayer_continue_play), new OnClickListener() {
@Override
public void onClick(View v) {
hideStatusView();
VideoViewManager.instance().setPlayOnMobileNetwork(true);
mMediaPlayer.start();
}
});
this.addView(mStatusView);
}
public void hideStatusView() {
this.removeView(mStatusView);
}
public void setPlayerState(int playerState) {
}
protected void doPauseResume() {
if (mCurrentPlayState == VideoView.STATE_BUFFERING) return;
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
} else {
mMediaPlayer.start();
}
}
/**
* 横竖屏切换
*/
protected void doStartStopFullScreen() {
Activity activity = PlayerUtils.scanForActivity(getContext());
if (activity == null) return;
if (mMediaPlayer.isFullScreen()) {
mMediaPlayer.stopFullScreen();
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
} else {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mMediaPlayer.startFullScreen();
}
}
protected Runnable mShowProgress = new Runnable() {
@Override
public void run() {
int pos = setProgress();
if (mMediaPlayer.isPlaying()) {
postDelayed(mShowProgress, 1000 - (pos % 1000));
}
}
};
protected final Runnable mFadeOut = new Runnable() {
@Override
public void run() {
hide();
}
};
protected int setProgress() {
return 0;
}
/**
* 获取当前系统时间
*/
protected String getCurrentSystemTime() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
Date date = new Date();
return simpleDateFormat.format(date);
}
protected String stringForTime(int timeMs) {
int totalSeconds = timeMs / 1000;
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
mFormatBuilder.setLength(0);
if (hours > 0) {
return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
} else {
return mFormatter.format("%02d:%02d", minutes, seconds).toString();
}
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
post(mShowProgress);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mShowProgress);
}
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
if (visibility == VISIBLE) {
post(mShowProgress);
}
}
/**
* 改变返回键逻辑,用于activity
*/
public boolean onBackPressed() {
return false;
}
public void setMediaPlayer(MediaPlayerControl mediaPlayer) {
this.mMediaPlayer = mediaPlayer;
}
}
package com.dueeeke.videoplayer.controller;
import android.content.Context;
import android.media.AudioManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.dueeeke.videoplayer.R;
import com.dueeeke.videoplayer.util.PlayerUtils;
import com.dueeeke.videoplayer.widget.CenterView;
/**
* 包含手势操作的VideoController
* Created by xinyu on 2018/1/6.
*/
public abstract class GestureVideoController extends BaseVideoController{
protected GestureDetector mGestureDetector;
protected boolean mIsGestureEnabled;
protected CenterView mCenterView;
protected AudioManager mAudioManager;
public GestureVideoController(@NonNull Context context) {
super(context);
}
public GestureVideoController(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public GestureVideoController(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void initView() {
super.initView();
mCenterView = new CenterView(getContext());
mCenterView.setVisibility(GONE);
addView(mCenterView);
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mGestureDetector = new GestureDetector(getContext(), new MyGestureListener());
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
}
protected int mStreamVolume;
protected float mBrightness;
protected int mPosition;
protected boolean mNeedSeek;
protected class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private boolean mFirstTouch;
private boolean mChangePosition;
private boolean mChangeBrightness;
private boolean mChangeVolume;
@Override
public boolean onDown(MotionEvent e) {
if (!mIsGestureEnabled || PlayerUtils.isEdge(getContext(), e)) return super.onDown(e);
mStreamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mBrightness = PlayerUtils.scanForActivity(getContext()).getWindow().getAttributes().screenBrightness;
mFirstTouch = true;
mChangePosition = false;
mChangeBrightness = false;
mChangeVolume = false;
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (mShowing) {
hide();
} else {
show();
}
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
if (!mIsGestureEnabled || PlayerUtils.isEdge(getContext(), e1)) return super.onScroll(e1, e2, distanceX, distanceY);
float deltaX = e1.getX() - e2.getX();
float deltaY = e1.getY() - e2.getY();
if (mFirstTouch) {
mChangePosition = Math.abs(distanceX) >= Math.abs(distanceY);
if (!mChangePosition) {
if (e2.getX() > PlayerUtils.getScreenWidth(getContext(), true) / 2) {
mChangeVolume = true;
} else {
mChangeBrightness = true;
}
}
mFirstTouch = false;
}
if (mChangePosition) {
slideToChangePosition(deltaX);
} else if (mChangeBrightness) {
slideToChangeBrightness(deltaY);
} else if (mChangeVolume) {
slideToChangeVolume(deltaY);
}
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
if (!mIsLocked) doPauseResume();
return true;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean detectedUp = event.getAction() == MotionEvent.ACTION_UP;
if (!mGestureDetector.onTouchEvent(event) && detectedUp) {
if (mCenterView.getVisibility() == VISIBLE) {
mCenterView.setVisibility(GONE);
}
if (mNeedSeek) {
mMediaPlayer.seekTo(mPosition);
mNeedSeek = false;
}
}
return super.onTouchEvent(event);
}
protected void slideToChangePosition(float deltaX) {
mCenterView.setVisibility(VISIBLE);
hide();
mCenterView.setProVisibility(View.GONE);
deltaX = -deltaX;
int width = getMeasuredWidth();
int duration = (int) mMediaPlayer.getDuration();
int currentPosition = (int) mMediaPlayer.getCurrentPosition();
int position = (int) (deltaX / width * 120000 + currentPosition);
if (position > currentPosition) {
mCenterView.setIcon(R.drawable.dkplayer_ic_action_fast_forward);
} else {
mCenterView.setIcon(R.drawable.dkplayer_ic_action_fast_rewind);
}
if (position > duration) position = duration;
if (position < 0) position = 0;
mPosition = position;
mCenterView.setTextView(stringForTime(position) + "/" + stringForTime(duration));
mNeedSeek = true;
}
protected void slideToChangeBrightness(float deltaY) {
mCenterView.setVisibility(VISIBLE);
hide();
mCenterView.setProVisibility(View.VISIBLE);
Window window = PlayerUtils.scanForActivity(getContext()).getWindow();
WindowManager.LayoutParams attributes = window.getAttributes();
mCenterView.setIcon(R.drawable.dkplayer_ic_action_brightness);
int height = getMeasuredHeight();
if (mBrightness == -1.0f) mBrightness = 0.5f;
float brightness = deltaY * 2 / height * 1.0f + mBrightness;
if (brightness < 0) {
brightness = 0f;
}
if (brightness > 1.0f) brightness = 1.0f;
int percent = (int) (brightness * 100);
mCenterView.setTextView(percent + "%");
mCenterView.setProPercent(percent);
attributes.screenBrightness = brightness;
window.setAttributes(attributes);
}
protected void slideToChangeVolume(float deltaY) {
mCenterView.setVisibility(VISIBLE);
hide();
mCenterView.setProVisibility(View.VISIBLE);
int streamMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int height = getMeasuredHeight();
float deltaV = deltaY * 2 / height * streamMaxVolume;
float index = mStreamVolume + deltaV;
if (index > streamMaxVolume) index = streamMaxVolume;
if (index < 0) {
mCenterView.setIcon(R.drawable.dkplayer_ic_action_volume_off);
index = 0;
} else {
mCenterView.setIcon(R.drawable.dkplayer_ic_action_volume_up);
}
int percent = (int) (index / streamMaxVolume * 100);
mCenterView.setTextView(percent + "%");
mCenterView.setProPercent(percent);
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) index, 0);
}
}
package com.dueeeke.videoplayer.controller;
import android.graphics.Bitmap;
public interface MediaPlayerControl {
void start();
void pause();
long getDuration();
long getCurrentPosition();
void seekTo(long pos);
boolean isPlaying();
int getBufferedPercentage();
void startFullScreen();
void stopFullScreen();
boolean isFullScreen();
void setMute(boolean isMute);
boolean isMute();
void setLock(boolean isLocked);
void setScreenScale(int screenScale);
void setSpeed(float speed);
long getTcpSpeed();
void replay(boolean resetPosition);
void setMirrorRotation(boolean enable);
Bitmap doScreenShot();
int[] getVideoSize();
void setRotation(float rotation);
void startTinyScreen();
void stopTinyScreen();
boolean isTinyScreen();
}
\ No newline at end of file
package com.dueeeke.videoplayer.listener;
public interface OnVideoViewStateChangeListener {
void onPlayerStateChanged(int playerState);
void onPlayStateChanged(int playState);
}
package com.dueeeke.videoplayer.listener;
/**
* Created by xinyu on 2017/12/21.
*/
public interface PlayerEventListener {
void onError();
void onCompletion();
void onInfo(int what, int extra);
void onPrepared();
void onVideoSizeChanged(int width, int height);
}
package com.dueeeke.videoplayer.player;
import android.content.res.AssetFileDescriptor;
import android.view.Surface;
import android.view.SurfaceHolder;
import com.dueeeke.videoplayer.listener.PlayerEventListener;
import java.util.List;
import java.util.Map;
/**
* Created by Devlin_n on 2017/12/21.
*/
public abstract class AbstractPlayer {
/**
* 开始渲染视频画面
*/
public static final int MEDIA_INFO_VIDEO_RENDERING_START = 3;
/**
* 缓冲开始
*/
public static final int MEDIA_INFO_BUFFERING_START = 701;
/**
* 缓冲结束
*/
public static final int MEDIA_INFO_BUFFERING_END = 702;
/**
* 视频旋转信息
*/
public static final int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;
/**
* 播放器事件回调
*/
protected PlayerEventListener mPlayerEventListener;
/**
* 初始化播放器实例
*/
public abstract void initPlayer();
/**
* 设置播放地址
* @param path 播放地址
* @param headers 播放地址请求头
*/
public abstract void setDataSource(String path, Map<String, String> headers);
/**
* 用于播放raw和asset里面的视频文件
*/
public abstract void setDataSource(AssetFileDescriptor fd);
public abstract void setDataSource(List<String> paths);
/**
* 播放
*/
public abstract void start();
/**
* 暂停
*/
public abstract void pause();
/**
* 停止
*/
public abstract void stop();
/**
* 准备开始播放(异步)
*/
public abstract void prepareAsync();
/**
* 重置播放器
*/
public abstract void reset();
/**
* 是否正在播放
*/
public abstract boolean isPlaying();
/**
* 调整进度
*/
public abstract void seekTo(long time);
/**
* 释放播放器
*/
public abstract void release();
/**
* 获取当前播放的位置
*/
public abstract long getCurrentPosition();
/**
* 获取视频总时长
*/
public abstract long getDuration();
/**
* 获取缓冲百分比
*/
public abstract int getBufferedPercentage();
/**
* 设置渲染视频的View,主要用于TextureView
*/
public abstract void setSurface(Surface surface);
/**
* 设置渲染视频的View,主要用于SurfaceView
*/
public abstract void setDisplay(SurfaceHolder holder);
/**
* 设置音量
*/
public abstract void setVolume(float v1, float v2);
/**
* 设置是否循环播放
*/
public abstract void setLooping(boolean isLooping);
/**
* 设置硬解码
*/
public abstract void setEnableMediaCodec(boolean isEnable);
/**
* 设置其他播放配置
*/
public abstract void setOptions();
/**
* 设置播放速度
*/
public abstract void setSpeed(float speed);
/**
* 获取当前缓冲的网速
*/
public abstract long getTcpSpeed();
/**
* 绑定VideoView
*/
public void setPlayerEventListener(PlayerEventListener playerEventListener) {
this.mPlayerEventListener = playerEventListener;
}
}
package com.dueeeke.videoplayer.player;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.view.Surface;
import android.view.SurfaceHolder;
import java.util.List;
import java.util.Map;
public class AndroidMediaPlayer extends AbstractPlayer {
protected MediaPlayer mMediaPlayer;
private boolean isLooping;
protected Context mAppContext;
private int mBufferedPercent;
public AndroidMediaPlayer(Context context) {
mAppContext = context.getApplicationContext();
}
@Override
public void initPlayer() {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setOnErrorListener(onErrorListener);
mMediaPlayer.setOnCompletionListener(onCompletionListener);
mMediaPlayer.setOnInfoListener(onInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(onBufferingUpdateListener);
mMediaPlayer.setOnPreparedListener(onPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
}
@Override
public void setDataSource(String path, Map<String, String> headers) {
try {
mMediaPlayer.setDataSource(mAppContext, Uri.parse(path), headers);
} catch (Exception e) {
mPlayerEventListener.onError();
}
}
@Override
public void setDataSource(AssetFileDescriptor fd) {
try {
mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
} catch (Exception e) {
mPlayerEventListener.onError();
}
}
@Override
public void setDataSource(List<String> paths) {
}
@Override
public void start() {
try {
mMediaPlayer.start();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
@Override
public void pause() {
try {
mMediaPlayer.pause();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
@Override
public void stop() {
try {
mMediaPlayer.stop();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
@Override
public void prepareAsync() {
try {
mMediaPlayer.prepareAsync();
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
@Override
public void reset() {
mMediaPlayer.release();
initPlayer();
mMediaPlayer.setVolume(1, 1);
mMediaPlayer.setLooping(isLooping);
}
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
@Override
public void seekTo(long time) {
try {
mMediaPlayer.seekTo((int) time);
} catch (IllegalStateException e) {
mPlayerEventListener.onError();
}
}
@Override
public void release() {
new Thread() {
@Override
public void run() {
try {
mMediaPlayer.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
@Override
public long getCurrentPosition() {
return mMediaPlayer.getCurrentPosition();
}
@Override
public long getDuration() {
return mMediaPlayer.getDuration();
}
@Override
public int getBufferedPercentage() {
return mBufferedPercent;
}
@Override
public void setSurface(Surface surface) {
mMediaPlayer.setSurface(surface);
}
@Override
public void setDisplay(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);
}
@Override
public void setVolume(float v1, float v2) {
mMediaPlayer.setVolume(v1, v2);
}
@Override
public void setLooping(boolean isLooping) {
this.isLooping = isLooping;
mMediaPlayer.setLooping(isLooping);
}
@Override
public void setEnableMediaCodec(boolean isEnable) {
// no support
}
@Override
public void setOptions() {
// no support
}
@Override
public void setSpeed(float speed) {
// no support
}
@Override
public long getTcpSpeed() {
// no support
return 0;
}
private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mPlayerEventListener.onError();
return true;
}
};
private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mPlayerEventListener.onCompletion();
}
};
private MediaPlayer.OnInfoListener onInfoListener = new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
mPlayerEventListener.onInfo(what, extra);
return true;
}
};
private MediaPlayer.OnBufferingUpdateListener onBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
mBufferedPercent = percent;
}
};
private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mPlayerEventListener.onPrepared();
mMediaPlayer.start();
}
};
private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
int videoWidth = mp.getVideoWidth();
int videoHeight = mp.getVideoHeight();
if (videoWidth != 0 && videoHeight != 0) {
mPlayerEventListener.onVideoSizeChanged(videoWidth, videoHeight);
}
}
};
}
package com.dueeeke.videoplayer.player;
import android.content.Context;
public class AndroidMediaPlayerFactory extends PlayerFactory {
private Context mContext;
public AndroidMediaPlayerFactory(Context context) {
mContext = context.getApplicationContext();
}
public static AndroidMediaPlayerFactory create(Context context) {
return new AndroidMediaPlayerFactory(context);
}
@Override
public AbstractPlayer createPlayer() {
return new AndroidMediaPlayer(mContext);
}
}
package com.dueeeke.videoplayer.player;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
/**
* 由于IjkPlayer已经不再更新,后续不再基于IjkPlayer进行开发,而是将本框架打造成一个通用的播放器框架
* 保留此类目的仅为向下兼容,后续版本将会移除
* @deprecated 使用 {@link VideoView} 代替
*/
@Deprecated
public class IjkVideoView extends VideoView {
public IjkVideoView(@NonNull Context context) {
super(context);
}
public IjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public IjkVideoView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
\ No newline at end of file
package com.dueeeke.videoplayer.player;
public abstract class PlayerFactory {
public abstract AbstractPlayer createPlayer();
}
package com.dueeeke.videoplayer.player;
public abstract class ProgressManager {
public abstract void saveProgress(String url, long progress);
public abstract long getSavedProgress(String url);
}
package com.dueeeke.videoplayer.player;
import android.support.annotation.Nullable;
/**
* 播放器全局配置
*/
public class VideoViewConfig {
public static Builder newBuilder() {
return new Builder();
}
public final boolean mPlayOnMobileNetwork;
public final boolean mEnableMediaCodec;
public final boolean mUsingSurfaceView;
public final boolean mAutoRotate;
public final boolean mEnableAudioFocus;
public final boolean mEnableParallelPlay;
public final boolean mIsEnableLog;
public final ProgressManager mProgressManager;
public final PlayerFactory mPlayerFactory;
public final int mScreenScaleType;
private VideoViewConfig(Builder builder) {
mIsEnableLog = builder.mIsEnableLog;
mAutoRotate = builder.mAutoRotate;
mUsingSurfaceView = builder.mUsingSurfaceView;
mPlayOnMobileNetwork = builder.mPlayOnMobileNetwork;
mEnableMediaCodec = builder.mEnableMediaCodec;
mEnableAudioFocus = builder.mEnableAudioFocus;
mProgressManager = builder.mProgressManager;
mEnableParallelPlay = builder.mEnableParallelPlay;
mPlayerFactory = builder.mPlayerFactory;
mScreenScaleType = builder.mScreenScaleType;
}
public final static class Builder {
private boolean mIsEnableLog;
private boolean mPlayOnMobileNetwork;
private boolean mUsingSurfaceView;
private boolean mAutoRotate;
private boolean mEnableMediaCodec;
private boolean mEnableAudioFocus = true;
private boolean mEnableParallelPlay;
private ProgressManager mProgressManager;
private PlayerFactory mPlayerFactory;
private int mScreenScaleType;
/**
* 是否通过重力感应切换全屏/半屏播放器, 默认不开启
*/
public Builder setAutoRotate(boolean autoRotate) {
mAutoRotate = autoRotate;
return this;
}
/**
* 是否启用SurfaceView,默认不启用
*/
public Builder setUsingSurfaceView(boolean usingSurfaceView) {
mUsingSurfaceView = usingSurfaceView;
return this;
}
/**
* 是否使用MediaCodec进行解码(硬解码),默认不开启,使用软解
*/
public Builder setEnableMediaCodec(boolean enableMediaCodec) {
mEnableMediaCodec = enableMediaCodec;
return this;
}
/**
* 在移动环境下调用start()后是否继续播放,默认不继续播放
*/
public Builder setPlayOnMobileNetwork(boolean playOnMobileNetwork) {
mPlayOnMobileNetwork = playOnMobileNetwork;
return this;
}
/**
* 是否开启AudioFocus监听, 默认开启
*/
public Builder setEnableAudioFocus(boolean enableAudioFocus) {
mEnableAudioFocus = enableAudioFocus;
return this;
}
/**
* 设置进度管理器,用于保存播放进度
*/
public Builder setProgressManager(@Nullable ProgressManager progressManager) {
mProgressManager = progressManager;
return this;
}
/**
* 支持多开
*/
public Builder setEnableParallelPlay(boolean enableParallelPlay) {
mEnableParallelPlay = enableParallelPlay;
return this;
}
/**
* 是否打印日志
*/
public Builder setLogEnabled(boolean enableLog) {
mIsEnableLog = enableLog;
return this;
}
/**
* 自定义播放核心
*/
public Builder setPlayerFactory(PlayerFactory playerFactory) {
mPlayerFactory = playerFactory;
return this;
}
/**
* 设置视频比例
*/
public Builder setScreenScale(int screenScaleType) {
mScreenScaleType = screenScaleType;
return this;
}
public VideoViewConfig build() {
return new VideoViewConfig(this);
}
}
}
package com.dueeeke.videoplayer.player;
import java.util.ArrayList;
import java.util.List;
/**
* 视频播放器管理器,管理当前正在播放的VideoView,以及播放器配置
*/
public class VideoViewManager {
/**
* 当前正在播放的VideoView
*/
private List<VideoView> mVideoViews = new ArrayList<>();
private boolean mPlayOnMobileNetwork;
private VideoViewManager() {
mPlayOnMobileNetwork = getConfig().mPlayOnMobileNetwork;
}
private static VideoViewManager sInstance;
private static VideoViewConfig sConfig;
public static void setConfig(VideoViewConfig config) {
if (sConfig == null) {
synchronized (VideoViewConfig.class) {
if (sConfig == null) {
sConfig = config == null ? VideoViewConfig.newBuilder().build() : config;
}
}
}
}
public static VideoViewConfig getConfig() {
setConfig(null);
return sConfig;
}
public boolean playOnMobileNetwork() {
return mPlayOnMobileNetwork;
}
public void setPlayOnMobileNetwork(boolean playOnMobileNetwork) {
mPlayOnMobileNetwork = playOnMobileNetwork;
}
public static VideoViewManager instance() {
if (sInstance == null) {
synchronized (VideoViewManager.class) {
if (sInstance == null) {
sInstance = new VideoViewManager();
}
}
}
return sInstance;
}
public void addVideoView(VideoView videoView) {
mVideoViews.add(videoView);
}
public void removeVideoView(VideoView videoView) {
mVideoViews.remove(videoView);
}
public List<VideoView> getVideoViews() {
return mVideoViews;
}
@Deprecated
public void releaseVideoPlayer() {
release();
}
public void pause() {
for (int i = 0; i < mVideoViews.size(); i++) {
VideoView vv = mVideoViews.get(i);
if (vv != null) {
vv.pause();
}
}
}
public void resume() {
for (int i = 0; i < mVideoViews.size(); i++) {
VideoView vv = mVideoViews.get(i);
if (vv != null) {
vv.resume();
}
}
}
public void release() {
for (int i = 0; i < mVideoViews.size(); i++) {
VideoView vv = mVideoViews.get(i);
if (vv != null) {
vv.release();
i--;
}
}
}
public boolean onBackPressed() {
for (int i = 0; i < mVideoViews.size(); i++) {
VideoView vv = mVideoViews.get(i);
if (vv != null) {
boolean b = vv.onBackPressed();
if (b) return true;
}
}
return false;
}
}
package com.dueeeke.videoplayer.util;
import android.util.Log;
import com.dueeeke.videoplayer.player.VideoViewManager;
/**
* 日志类
* Created by Devlin_n on 2017/6/5.
*/
public class L {
private static final String TAG = "DKPlayer";
private static boolean isDebug = VideoViewManager.getConfig().mIsEnableLog;
public static void d(String msg) {
if (isDebug) {
Log.d(TAG, msg);
}
}
public static void e(String msg) {
if (isDebug) {
Log.e(TAG, msg);
}
}
public static void i(String msg) {
if (isDebug) {
Log.i(TAG, msg);
}
}
public static void w(Throwable e) {
if (isDebug) {
Log.w(TAG, e);
}
}
public static void setDebug(boolean isDebug) {
L.isDebug = isDebug;
}
}
package com.dueeeke.videoplayer.util;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
import android.graphics.Point;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.TypedValue;
import android.view.Display;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.WindowManager;
/**
* 播放器相关工具类
* Created by Devlin_n on 2017/4/10.
*/
public class PlayerUtils {
/**
* 获取状态栏高度
*/
public static double getStatusBarHeight(Context context) {
int statusBarHeight = 0;
//获取status_bar_height资源的ID
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
//根据资源ID获取响应的尺寸值
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
/**
* 获取NavigationBar的高度
*/
public static int getNavigationBarHeight(Context context) {
if (!hasNavigationBar(context)) {
return 0;
}
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
//获取NavigationBar的高度
return resources.getDimensionPixelSize(resourceId);
}
/**
* 是否存在NavigationBar
*/
public static boolean hasNavigationBar(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
Display display = getWindowManager(context).getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
return realSize.x != size.x || realSize.y != size.y;
} else {
boolean menu = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
return !(menu || back);
}
}
/**
* 获取屏幕宽度
*/
public static int getScreenWidth(Context context, boolean isIncludeNav) {
if (isIncludeNav) {
return context.getResources().getDisplayMetrics().widthPixels + getNavigationBarHeight(context);
} else {
return context.getResources().getDisplayMetrics().widthPixels;
}
}
/**
* 获取屏幕高度
*/
public static int getScreenHeight(Context context, boolean isIncludeNav) {
if (isIncludeNav) {
return context.getResources().getDisplayMetrics().heightPixels + getNavigationBarHeight(context);
} else {
return context.getResources().getDisplayMetrics().heightPixels;
}
}
/**
* 获取Activity
*/
public static Activity scanForActivity(Context context) {
return context == null ? null : (context instanceof Activity ? (Activity) context : (context instanceof ContextWrapper ? scanForActivity(((ContextWrapper) context).getBaseContext()) : null));
}
/**
* dp转为px
*/
public static int dp2px(Context context, float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, context.getResources().getDisplayMetrics());
}
/**
* sp转为px
*/
public static int sp2px(Context context, float dpValue) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, dpValue, context.getResources().getDisplayMetrics());
}
/**
* 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。
*/
public static WindowManager getWindowManager(Context context) {
return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
}
/**
* 边缘检测
*/
public static boolean isEdge(Context context, MotionEvent e) {
int edgeSize = dp2px(context, 40);
return e.getRawX() < edgeSize
|| e.getRawX() > getScreenWidth(context, true) - edgeSize
|| e.getRawY() < edgeSize
|| e.getRawY() > getScreenHeight(context, true) - edgeSize;
}
public static final int NO_NETWORK = 0;
public static final int NETWORK_CLOSED = 1;
public static final int NETWORK_ETHERNET = 2;
public static final int NETWORK_WIFI = 3;
public static final int NETWORK_MOBILE = 4;
public static final int NETWORK_UNKNOWN = -1;
/**
* 判断当前网络类型-1为未知网络0为没有网络连接1网络断开或关闭2为以太网3为WiFi4为2G5为3G6为4G
*/
public static int getNetworkType(Context context) {
//改为context.getApplicationContext(),防止在Android 6.0上发生内存泄漏
ConnectivityManager connectMgr = (ConnectivityManager) context.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectMgr == null) {
return NO_NETWORK;
}
NetworkInfo networkInfo = connectMgr.getActiveNetworkInfo();
if (networkInfo == null) {
// 没有任何网络
return NO_NETWORK;
}
if (!networkInfo.isConnected()) {
// 网络断开或关闭
return NETWORK_CLOSED;
}
if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
// 以太网网络
return NETWORK_ETHERNET;
} else if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
// wifi网络,当激活时,默认情况下,所有的数据流量将使用此连接
return NETWORK_WIFI;
} else if (networkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
// 移动数据连接,不能与连接共存,如果wifi打开,则自动关闭
switch (networkInfo.getSubtype()) {
case TelephonyManager.NETWORK_TYPE_GPRS:
case TelephonyManager.NETWORK_TYPE_EDGE:
case TelephonyManager.NETWORK_TYPE_CDMA:
case TelephonyManager.NETWORK_TYPE_1xRTT:
case TelephonyManager.NETWORK_TYPE_IDEN:
// 2G网络
case TelephonyManager.NETWORK_TYPE_UMTS:
case TelephonyManager.NETWORK_TYPE_EVDO_0:
case TelephonyManager.NETWORK_TYPE_EVDO_A:
case TelephonyManager.NETWORK_TYPE_HSDPA:
case TelephonyManager.NETWORK_TYPE_HSUPA:
case TelephonyManager.NETWORK_TYPE_HSPA:
case TelephonyManager.NETWORK_TYPE_EVDO_B:
case TelephonyManager.NETWORK_TYPE_EHRPD:
case TelephonyManager.NETWORK_TYPE_HSPAP:
// 3G网络
case TelephonyManager.NETWORK_TYPE_LTE:
// 4G网络
return NETWORK_MOBILE;
}
}
// 未知网络
return NETWORK_UNKNOWN;
}
}
package com.dueeeke.videoplayer.widget;
import android.content.Context;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.dueeeke.videoplayer.R;
/**
* 显示亮度,音量,进度
* Created by Devlin_n on 2017/4/17.
*/
public class CenterView extends LinearLayout {
private ImageView ivIcon;
private TextView tvPercent;
private ProgressBar proPercent;
public CenterView(Context context) {
super(context);
init();
}
private void init() {
setGravity(Gravity.CENTER);
View view = LayoutInflater.from(getContext()).inflate(R.layout.dkplayer_layout_center_window, this);
ivIcon = view.findViewById(R.id.iv_icon);
tvPercent = view.findViewById(R.id.tv_percent);
proPercent = view.findViewById(R.id.pro_percent);
}
public void setIcon(int icon) {
if (ivIcon != null) ivIcon.setImageResource(icon);
}
public void setTextView(String text) {
if (tvPercent != null) tvPercent.setText(text);
}
public void setProPercent(int percent) {
if (proPercent != null) proPercent.setProgress(percent);
}
public void setProVisibility(int visibility) {
if (proPercent != null) proPercent.setVisibility(visibility);
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
if (visibility != VISIBLE) {
Animation animation = AnimationUtils.loadAnimation(getContext(), R.anim.dkplayer_anim_center_view);
this.startAnimation(animation);
}
}
}
package com.dueeeke.videoplayer.widget;
import android.graphics.Bitmap;
import android.view.View;
public interface IRenderView {
/**
* 设置视频宽高
* @param videoWidth 宽
* @param videoHeight 高
*/
void setVideoSize(int videoWidth, int videoHeight);
/**
* 设置视频旋转角度
* @param degree 角度值
*/
void setVideoRotation(int degree);
/**
* 设置screen scale type
* @param scaleType 类型
*/
void setScaleType(int scaleType);
/**
* 获取真实的RenderView
*/
View getView();
/**
* 截图
*/
Bitmap doScreenShot();
/**
* 释放资源
*/
void release();
}
\ No newline at end of file
package com.dueeeke.videoplayer.widget;
import android.view.View;
import com.dueeeke.videoplayer.player.VideoView;
public class MeasureHelper {
private int mVideoWidth;
private int mVideoHeight;
private int mCurrentScreenScale;
private int mVideoRotationDegree;
public void setVideoRotation(int videoRotationDegree) {
mVideoRotationDegree = videoRotationDegree;
}
public void setVideoSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
}
public void setScreenScale(int screenScale) {
mCurrentScreenScale = screenScale;
}
public int[] doMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) { // 软解码时处理旋转信息,交换宽高
widthMeasureSpec = widthMeasureSpec + heightMeasureSpec;
heightMeasureSpec = widthMeasureSpec - heightMeasureSpec;
widthMeasureSpec = widthMeasureSpec - heightMeasureSpec;
}
int width = View.getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = View.getDefaultSize(mVideoHeight, heightMeasureSpec);
//如果设置了比例
switch (mCurrentScreenScale) {
case VideoView.SCREEN_SCALE_ORIGINAL:
width = mVideoWidth;
height = mVideoHeight;
break;
case VideoView.SCREEN_SCALE_16_9:
if (height > width / 16 * 9) {
height = width / 16 * 9;
} else {
width = height / 9 * 16;
}
break;
case VideoView.SCREEN_SCALE_4_3:
if (height > width / 4 * 3) {
height = width / 4 * 3;
} else {
width = height / 3 * 4;
}
// Log.d("@@@@", "onMeasure 4:3 : width" + width + " height:" + height);
break;
case VideoView.SCREEN_SCALE_MATCH_PARENT:
width = widthMeasureSpec;
height = heightMeasureSpec;
break;
case VideoView.SCREEN_SCALE_CENTER_CROP:
if (mVideoWidth > 0 && mVideoHeight > 0) {
if (mVideoWidth * height > width * mVideoHeight) {
width = height * mVideoWidth / mVideoHeight;
} else {
height = width * mVideoHeight / mVideoWidth;
}
}
break;
case VideoView.SCREEN_SCALE_DEFAULT:
default:
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == View.MeasureSpec.EXACTLY && heightSpecMode == View.MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == View.MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == View.MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == View.MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == View.MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
break;
}
return new int[]{width, height};
}
}
package com.dueeeke.videoplayer.widget;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.dueeeke.videoplayer.R;
/**
* 错误提示,网络提示
* Created by Devlin_n on 2017/4/13.
*/
public class StatusView extends LinearLayout {
private TextView tvMessage;
private TextView btnAction;
private float downX;
private float downY;
public StatusView(Context context) {
this(context, null);
}
public StatusView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
View root = LayoutInflater.from(getContext()).inflate(R.layout.dkplayer_layout_status_view, this);
tvMessage = root.findViewById(R.id.message);
btnAction = root.findViewById(R.id.status_btn);
this.setBackgroundResource(android.R.color.black);
setClickable(true);
}
public void setMessage(String msg) {
if (tvMessage != null) tvMessage.setText(msg);
}
public void setButtonTextAndAction(String text, OnClickListener listener) {
if (btnAction != null) {
btnAction.setText(text);
btnAction.setOnClickListener(listener);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = ev.getX();
downY = ev.getY();
// True if the child does not want the parent to intercept touch events.
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
float absDeltaX = Math.abs(ev.getX() - downX);
float absDeltaY = Math.abs(ev.getY() - downY);
if (absDeltaX > ViewConfiguration.get(getContext()).getScaledTouchSlop() ||
absDeltaY > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
getParent().requestDisallowInterceptTouchEvent(false);
}
case MotionEvent.ACTION_UP:
break;
}
return super.dispatchTouchEvent(ev);
}
}
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1"
android:toAlpha="0"
android:duration="300">
</alpha>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<solid android:color="#cc999999"/>
<size android:height="1dp"/>
</shape>
</item>
<item android:id="@android:id/secondaryProgress">
<clip>
<shape>
<solid android:color="@android:color/white"/>
<size android:height="1dp"/>
</shape>
</clip>
</item>
<item android:id="@android:id/progress">
<clip>
<shape>
<solid android:color="@color/dkplayer_theme_color"/>
<size android:height="1dp"/>
</shape>
</clip>
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/dkplayer_theme_color"/>
<corners android:radius="30dp"/>
</shape>
\ No newline at end of file
<resources>
<string name="dkplayer_error_message">Something went wrong, please try again later</string>
<string name="dkplayer_retry"> Retry </string>
<string name="dkplayer_continue_play">Continue playing</string>
<string name="dkplayer_wifi_tip">You are currently using the mobile network, and continuing to play will consume traffic</string>
</resources>
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="dkplayer_theme_color">#39C5BB</color>
</resources>
\ No newline at end of file
<resources>
<string name="dkplayer_error_message">出了点小问题,请稍后重试</string>
<string name="dkplayer_retry"> 重 试 </string>
<string name="dkplayer_continue_play">继续播放</string>
<string name="dkplayer_wifi_tip">您正在使用移动网络,继续播放将消耗流量</string>
</resources>
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