Commit 4f1878848ec875f1f50e659cc75d6f63c3981b20

Authored by 朱显松
1 parent 224ada73

企业端专属分支

Showing 26 changed files with 3499 additions and 42 deletions
build.gradle
@@ -63,7 +63,7 @@ ext { @@ -63,7 +63,7 @@ ext {
63 qmui = '1.1.5' 63 qmui = '1.1.5'
64 64
65 libLargeImage = '1.0.4-androidx' 65 libLargeImage = '1.0.4-androidx'
66 - libBase = '1.9.9.0' 66 + libBase = '2.0.0.7.3'
67 libVideoQiniu = '1.0.7.2' 67 libVideoQiniu = '1.0.7.2'
68 68
69 //阿里路由框架 69 //阿里路由框架
config.gradle
@@ -21,7 +21,7 @@ ext { @@ -21,7 +21,7 @@ ext {
21 //编译方式 21 //编译方式
22 debug : false, 22 debug : false,
23 //版本号 23 //版本号
24 - version: "1.1.3", 24 + version: "1.1.3.7",
25 //Lib库前缀 25 //Lib库前缀
26 packeg : "com.cnlive.media", 26 packeg : "com.cnlive.media",
27 //Lib库名称 27 //Lib库名称
lib_media/build.gradle
@@ -48,7 +48,7 @@ dependencies { @@ -48,7 +48,7 @@ dependencies {
48 annotationProcessor "com.github.bumptech.glide:compiler:$rootProject.compiler" 48 annotationProcessor "com.github.bumptech.glide:compiler:$rootProject.compiler"
49 49
50 //视讯云SDK 50 //视讯云SDK
51 - implementation "com.qmuiteam:qmui:$rootProject.qmui" 51 +// implementation "com.qmuiteam:qmui:$rootProject.qmui"
52 52
53 implementation "com.cnlive.libs:base:$rootProject.libBase" 53 implementation "com.cnlive.libs:base:$rootProject.libBase"
54 implementation 'com.github.chrisbanes:PhotoView:2.1.4' 54 implementation 'com.github.chrisbanes:PhotoView:2.1.4'
lib_media/src/main/java/com/cnlive/libs/base/frame/ReflectUtil.java 0 → 100644
  1 +package com.cnlive.libs.base.frame;
  2 +
  3 +
  4 +import java.lang.reflect.Constructor;
  5 +import java.lang.reflect.Method;
  6 +import java.lang.reflect.ParameterizedType;
  7 +
  8 +public class ReflectUtil {
  9 +
  10 + private static final String TAG = "ReflectUtil";
  11 +
  12 + public static Object invoke(Object obj, String methodName, Object data, Class clazz) {
  13 + Object result = null;
  14 + try {
  15 + Method method = obj.getClass().getMethod(methodName, clazz);
  16 + result = method.invoke(obj, data);
  17 + } catch (Exception ignored) {
  18 + }
  19 + return result;
  20 + }
  21 +
  22 + public static Object invoke(Object obj, String methodName, Object data) {
  23 + Object result = null;
  24 + try {
  25 + Method method = obj.getClass().getMethod(methodName, new Class[]{data.getClass()});
  26 + result = method.invoke(obj, data);
  27 + } catch (Exception ignored) {
  28 + }
  29 + return result;
  30 + }
  31 +
  32 + public static Object invoke(Object obj, String methodName) {
  33 + Object result = null;
  34 + try {
  35 + Method method = obj.getClass().getMethod(methodName);
  36 + result = method.invoke(obj);
  37 + } catch (Exception ignored) {
  38 + }
  39 + return result;
  40 + }
  41 +
  42 + public static <R> R instance(int position, Class type, Object data) {
  43 + R result = null;
  44 + try {
  45 + ParameterizedType pt = (ParameterizedType) type.getGenericSuperclass();
  46 + Class<R> clazz = (Class<R>) pt.getActualTypeArguments()[position];
  47 + Constructor constructor = clazz.getConstructor(new Class[]{data.getClass()});
  48 + result = (R) constructor.newInstance(data);
  49 + } catch (Exception ignored) {
  50 + }
  51 + return result;
  52 + }
  53 +
  54 + public static <R> R instance(int position, Object object) {
  55 + R result = null;
  56 + try {
  57 + ParameterizedType pt = (ParameterizedType) object.getClass().getGenericSuperclass();
  58 + Class<R> clazz = (Class<R>) pt.getActualTypeArguments()[position];
  59 + result = clazz.newInstance();
  60 + } catch (Exception ignored) {
  61 + }
  62 + return result;
  63 + }
  64 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpActivity.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.activity;
  2 +
  3 +import android.os.Bundle;
  4 +import androidx.annotation.NonNull;
  5 +
  6 +import com.cnlive.libs.base.frame.ReflectUtil;
  7 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  8 +import com.hannesdorfmann.mosby3.mvp.MvpView;
  9 +
  10 +/**
  11 + * MVP Databinding Base Activity
  12 + * @param <V> MVP View {@link MvpView}
  13 + * @param <P> MVP Presenter {@link MvpPresenter}
  14 + */
  15 +public abstract class MvpActivity<V extends MvpView, P extends MvpPresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpActivity<V, P> {
  16 +
  17 + public V view;
  18 +
  19 + @Override
  20 + protected void onCreate(Bundle savedInstanceState) {
  21 + super.onCreate(savedInstanceState);
  22 + setContentView(getLayoutId());
  23 + }
  24 +
  25 + protected abstract int getLayoutId();
  26 +
  27 + @NonNull
  28 + public V createView() {
  29 + return ReflectUtil.instance(0, this.getClass(), this);
  30 + }
  31 +
  32 + @NonNull
  33 + @Override
  34 + public P createPresenter() {
  35 + return ReflectUtil.instance(1, this);
  36 + }
  37 +
  38 + @NonNull
  39 + @Override
  40 + public V getMvpView() {
  41 + if (view == null) view = createView();
  42 + return view;
  43 + }
  44 +
  45 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpBindingActivity.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.activity;
  2 +
  3 +import androidx.databinding.DataBindingUtil;
  4 +import androidx.databinding.ViewDataBinding;
  5 +import android.os.Bundle;
  6 +import androidx.annotation.NonNull;
  7 +
  8 +import com.cnlive.libs.base.frame.ReflectUtil;
  9 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  10 +import com.hannesdorfmann.mosby3.mvp.MvpView;
  11 +
  12 +/**
  13 + * MVP Databinding Base Activity
  14 + * @param <V> MVP View {@link MvpView}
  15 + * @param <P> MVP Presenter {@link MvpPresenter}
  16 + * @param <D> Databind Page Data
  17 + * @param <T> Databind Activity ViewDataBinding {@link ViewDataBinding}
  18 + */
  19 +public abstract class MvpBindingActivity<V extends MvpView, P extends MvpPresenter<V>, D, T extends ViewDataBinding> extends MvpActivity<V, P> {
  20 +
  21 + public T binding;
  22 + public D data;
  23 +
  24 + @Override
  25 + protected void onCreate(Bundle savedInstanceState) {
  26 + super.onCreate(savedInstanceState);
  27 + binding = DataBindingUtil.setContentView(this, getLayoutId());
  28 + ReflectUtil.invoke(binding, "setData", getViewData());
  29 + }
  30 +
  31 + protected D initLayoutData() {
  32 + return ReflectUtil.instance(2, this);
  33 + }
  34 +
  35 + @NonNull
  36 + public D getViewData() {
  37 + if (data == null) data = initLayoutData();
  38 + return data;
  39 + }
  40 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpLceActivity.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.activity;
  2 +
  3 +import android.os.Bundle;
  4 +import android.view.View;
  5 +import android.widget.Toast;
  6 +
  7 +import androidx.annotation.NonNull;
  8 +
  9 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  10 +import com.hannesdorfmann.mosby3.mvp.lce.LceAnimator;
  11 +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView;
  12 +
  13 +/**
  14 + * Created by Lynn on 2017/8/30.
  15 + */
  16 +
  17 +public abstract class MvpLceActivity<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>>
  18 + extends com.hannesdorfmann.mosby3.mvp.MvpActivity<V, P> implements MvpLceView<M> {
  19 +
  20 + protected View loadingView;
  21 + protected CV contentView;
  22 + protected View errorView;
  23 +
  24 + @Override
  25 + protected void onCreate(Bundle savedInstanceState) {
  26 + super.onCreate(savedInstanceState);
  27 + setContentView(getLayoutId());
  28 + }
  29 +
  30 + @Override
  31 + public void onContentChanged() {
  32 + super.onContentChanged();
  33 +
  34 + loadingView = findViewById(loadingViewId());
  35 + contentView = (CV) findViewById(contentViewId());
  36 + errorView = findViewById(errorViewId());
  37 +
  38 + if (loadingView == null) {
  39 + throw new NullPointerException(
  40 + "Loading view is null! Have you specified a loading view in your layout xml file?");
  41 + }
  42 +
  43 + if (contentView == null) {
  44 + throw new NullPointerException(
  45 + "Content view is null! Have you specified a content view in your layout xml file?");
  46 + }
  47 +
  48 + if (errorView == null) {
  49 + throw new NullPointerException(
  50 + "Error view is null! Have you specified an error view in your layout xml file?");
  51 + }
  52 +
  53 + }
  54 +
  55 + @NonNull
  56 + public abstract int loadingViewId();
  57 +
  58 + @NonNull
  59 + public abstract int contentViewId();
  60 +
  61 + @NonNull
  62 + public abstract int errorViewId();
  63 +
  64 + public abstract int getLayoutId();
  65 +
  66 + @NonNull
  67 + @Override
  68 + public P createPresenter() {
  69 + return null;
  70 + }
  71 +
  72 + @Override
  73 + public void showLoading(boolean pullToRefresh) {
  74 +
  75 + if (!pullToRefresh) {
  76 + animateLoadingViewIn();
  77 + }
  78 +
  79 + }
  80 +
  81 + protected void animateLoadingViewIn() {
  82 + LceAnimator.showLoading(loadingView, contentView, errorView);
  83 + }
  84 +
  85 + @Override
  86 + public void showContent() {
  87 + animateContentViewIn();
  88 + }
  89 +
  90 + protected void animateContentViewIn() {
  91 + LceAnimator.showContent(loadingView, contentView, errorView);
  92 + }
  93 +
  94 + protected abstract String getErrorMessage(Throwable e, boolean pullToRefresh);
  95 +
  96 + protected void showLightError(String msg) {
  97 + Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
  98 + }
  99 +
  100 + @Override
  101 + public void showError(Throwable e, boolean pullToRefresh) {
  102 +
  103 + String errorMsg = getErrorMessage(e, pullToRefresh);
  104 +
  105 + if (pullToRefresh) {
  106 + showLightError(errorMsg);
  107 + } else {
  108 + animateErrorViewIn();
  109 + }
  110 + }
  111 +
  112 + protected void animateErrorViewIn() {
  113 + LceAnimator.showErrorView(loadingView, contentView, errorView);
  114 + }
  115 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpLceBindingActivity.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.activity;
  2 +
  3 +import android.os.Bundle;
  4 +import android.view.View;
  5 +
  6 +import androidx.databinding.DataBindingUtil;
  7 +import androidx.databinding.ViewDataBinding;
  8 +
  9 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  10 +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView;
  11 +
  12 +/**
  13 + * Created by Lynn on 2017/8/30.
  14 + */
  15 +
  16 +public abstract class MvpLceBindingActivity<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>, T extends ViewDataBinding> extends MvpLceActivity<CV, M, V, P> {
  17 +
  18 + public T binding;
  19 +
  20 + @Override
  21 + protected void onCreate(Bundle savedInstanceState) {
  22 + super.onCreate(savedInstanceState);
  23 + binding = DataBindingUtil.setContentView(this, getLayoutId());
  24 + }
  25 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/activity/MvpViewStateActivity.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.activity;
  2 +
  3 +import android.os.Bundle;
  4 +import android.os.Parcelable;
  5 +import androidx.annotation.NonNull;
  6 +
  7 +import com.cnlive.libs.base.frame.ReflectUtil;
  8 +import com.cnlive.libs.base.frame.state.MvpViewState;
  9 +import com.cnlive.libs.base.frame.view.MvpStateView;
  10 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  11 +
  12 +/**
  13 + * Created by xiansong on 2017/8/25.
  14 + */
  15 +
  16 +public abstract class MvpViewStateActivity<V extends MvpStateView<D>, P extends MvpPresenter<V>, D extends Parcelable> extends com.hannesdorfmann.mosby3.mvp.viewstate.MvpViewStateActivity<V, P, MvpViewState<V, D>> {
  17 +
  18 + public V view;
  19 + public MvpViewState<V, D> viewState;
  20 +
  21 + protected abstract int getLayoutId();
  22 +
  23 + @Override
  24 + protected void onCreate(Bundle savedInstanceState) {
  25 + super.onCreate(savedInstanceState);
  26 + setContentView(getLayoutId());
  27 + }
  28 +
  29 + @NonNull
  30 + public V createView() {
  31 + return ReflectUtil.instance(0, this.getClass(), this);
  32 + }
  33 +
  34 + @NonNull
  35 + @Override
  36 + public P createPresenter() {
  37 + return ReflectUtil.instance(1, this);
  38 + }
  39 +
  40 + protected D initLayoutData() {
  41 + return ReflectUtil.instance(2, this);
  42 + }
  43 +
  44 + protected MvpViewState<V, D> initViewState() {
  45 + return new MvpViewState<>(initLayoutData());
  46 + }
  47 +
  48 + @NonNull
  49 + @Override
  50 + public MvpViewState<V, D> createViewState() {
  51 + if (viewState == null) {
  52 + viewState = initViewState();
  53 + }
  54 + return viewState;
  55 + }
  56 +
  57 + @NonNull
  58 + public D getViewData() {
  59 + return getViewState().getViewData();
  60 + }
  61 +
  62 + @NonNull
  63 + @Override
  64 + public V getMvpView() {
  65 + if (view == null) {
  66 + view = createView();
  67 + }
  68 + return view;
  69 + }
  70 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/adapter/DataBindingRecyclerAdapter.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.adapter;
  2 +
  3 +/**
  4 + * Created by xiansong on 2017/9/1.
  5 + */
  6 +
  7 +import androidx.databinding.DataBindingUtil;
  8 +import androidx.databinding.ViewDataBinding;
  9 +import androidx.annotation.NonNull;
  10 +import androidx.recyclerview.widget.RecyclerView;
  11 +import android.view.LayoutInflater;
  12 +import android.view.View;
  13 +import android.view.ViewGroup;
  14 +
  15 +import com.cnlive.libs.base.frame.ReflectUtil;
  16 +
  17 +import java.util.List;
  18 +
  19 +
  20 +public abstract class DataBindingRecyclerAdapter<D, T extends ViewDataBinding> extends RecyclerView.Adapter<DataBindingRecyclerAdapter<D, T>.DataBindingViewHolder> {
  21 +
  22 + class DataBindingViewHolder extends RecyclerView.ViewHolder {
  23 +
  24 + private ViewDataBinding binding;
  25 +
  26 + private DataBindingViewHolder(View itemView) {
  27 + super(itemView);
  28 + }
  29 +
  30 + public void setBinding(ViewDataBinding binding) {
  31 + this.binding = binding;
  32 + }
  33 +
  34 + public ViewDataBinding getBinding() {
  35 + return binding;
  36 + }
  37 + }
  38 +
  39 + abstract class Click implements View.OnClickListener {
  40 + int position;
  41 +
  42 + Click(int position) {
  43 + this.position = position;
  44 + }
  45 + }
  46 +
  47 + public interface OnItemClickListener<D> {
  48 + void onItemClick(int id, D item);
  49 + }
  50 +
  51 + public abstract int getLayoutId();
  52 +
  53 + public abstract List<D> getList();
  54 +
  55 + private OnItemClickListener<D> listener;
  56 +
  57 + @Override
  58 + public DataBindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
  59 + T binding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()), getLayoutId(), parent, false);
  60 + DataBindingViewHolder viewHolder = new DataBindingViewHolder(binding.getRoot());
  61 + viewHolder.setBinding(binding);
  62 + return viewHolder;
  63 + }
  64 +
  65 + @Override
  66 + public void onBindViewHolder(@NonNull final DataBindingViewHolder holder, int position) {
  67 + ReflectUtil.invoke(holder.binding, "setData", getList().get(position));
  68 + ReflectUtil.invoke(holder.binding, "setClick", new Click(position) {
  69 + @Override
  70 + public void onClick(View v) {
  71 +// if (listener != null) listener.onItemClick(v.getId(), getList().get(position));
  72 + if (listener != null)
  73 + listener.onItemClick(v.getId(), (D) ReflectUtil.invoke(holder.binding, "getData"));
  74 + }
  75 + }, View.OnClickListener.class);
  76 + holder.binding.executePendingBindings();
  77 + }
  78 +
  79 + public D getItem(int location) {
  80 + return getList().get(location);
  81 + }
  82 +
  83 + @Override
  84 + public int getItemCount() {
  85 + return getList() == null ? 0 : getList().size();
  86 + }
  87 +
  88 + public void setItemClickListener(OnItemClickListener<D> listener) {
  89 + this.listener = listener;
  90 + }
  91 +
  92 + public void addItem(int position, D item) {
  93 + if (item == null) return;
  94 + getList().add(position, item);
  95 + notifyItemInserted(position);
  96 + }
  97 +
  98 + public void addItem(D item) {
  99 + if (item == null) return;
  100 + getList().add(getList().size(), item);
  101 + notifyItemInserted(getList().size());
  102 + }
  103 +
  104 + public void addItems(List<D> items) {
  105 + if (items == null) return;
  106 + this.getList().addAll(items);
  107 + notifyDataSetChanged();
  108 + }
  109 +
  110 + public boolean containsAll(List<D> items) {
  111 + return getList().containsAll(items);
  112 + }
  113 +
  114 + public void updateItem(D tasks, int position) {
  115 + if (tasks == null) return;
  116 + getList().set(position, tasks);
  117 + notifyItemChanged(position);
  118 + }
  119 +
  120 + public void updateItems(List<D> items) {
  121 + if (items == null) return;
  122 + this.getList().clear();
  123 + this.getList().addAll(items);
  124 + notifyDataSetChanged();
  125 + }
  126 +
  127 + public void removeItem(int index) {
  128 + getList().remove(index);
  129 + notifyItemRemoved(index);
  130 + }
  131 +
  132 + public void removeAllItems() {
  133 + getList().clear();
  134 + notifyDataSetChanged();
  135 + }
  136 +}
0 \ No newline at end of file 137 \ No newline at end of file
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpBindingFragment.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.fragment;
  2 +
  3 +import androidx.databinding.DataBindingUtil;
  4 +import androidx.databinding.ViewDataBinding;
  5 +import android.os.Bundle;
  6 +import androidx.annotation.NonNull;
  7 +import androidx.annotation.Nullable;
  8 +import android.view.LayoutInflater;
  9 +import android.view.View;
  10 +import android.view.ViewGroup;
  11 +
  12 +import com.cnlive.libs.base.frame.ReflectUtil;
  13 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  14 +import com.hannesdorfmann.mosby3.mvp.MvpView;
  15 +
  16 +/**
  17 + * MVP Databinding Base Fragment
  18 + *
  19 + * @param <V> MVP View {@link MvpView}
  20 + * @param <P> MVP Presenter {@link MvpPresenter}
  21 + * @param <D> Databind Page Data
  22 + * @param <T> Databind Activity ViewDataBinding {@link ViewDataBinding}
  23 + */
  24 +public abstract class MvpBindingFragment<V extends MvpView, P extends MvpPresenter<V>, D, T extends ViewDataBinding> extends MvpFragment<V, P> {
  25 +
  26 + public T binding;
  27 + public D data;
  28 +
  29 + @Nullable
  30 + @Override
  31 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  32 + binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
  33 + ReflectUtil.invoke(binding, "setData", getViewData());
  34 + return binding.getRoot();
  35 + }
  36 +
  37 + protected D initLayoutData() {
  38 + return ReflectUtil.instance(2, this);
  39 + }
  40 +
  41 + @NonNull
  42 + public D getViewData() {
  43 + if (data == null) data = initLayoutData();
  44 + return data;
  45 + }
  46 +}
0 \ No newline at end of file 47 \ No newline at end of file
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpFragment.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.fragment;
  2 +
  3 +import android.os.Bundle;
  4 +import androidx.annotation.NonNull;
  5 +import androidx.annotation.Nullable;
  6 +import android.view.LayoutInflater;
  7 +import android.view.View;
  8 +import android.view.ViewGroup;
  9 +
  10 +import com.cnlive.libs.base.frame.ReflectUtil;
  11 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  12 +import com.hannesdorfmann.mosby3.mvp.MvpView;
  13 +
  14 +/**
  15 + * MVP Databinding Base Fragment
  16 + *
  17 + * @param <V> MVP View {@link MvpView}
  18 + * @param <P> MVP Presenter {@link MvpPresenter}
  19 + */
  20 +public abstract class MvpFragment<V extends MvpView, P extends MvpPresenter<V>> extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> {
  21 +
  22 + public V view;
  23 +
  24 + @Nullable
  25 + @Override
  26 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  27 + return inflater.inflate(getLayoutId(), container, false);
  28 + }
  29 +
  30 + protected abstract int getLayoutId();
  31 +
  32 + @NonNull
  33 + public V createView() {
  34 + return ReflectUtil.instance(0, this.getClass(), this);
  35 + }
  36 +
  37 + @NonNull
  38 + @Override
  39 + public P createPresenter() {
  40 + return ReflectUtil.instance(1, this);
  41 + }
  42 +
  43 + @NonNull
  44 + @Override
  45 + public V getMvpView() {
  46 + if (view == null) view = createView();
  47 + return view;
  48 + }
  49 +
  50 +}
0 \ No newline at end of file 51 \ No newline at end of file
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpLceBindingFragment.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.fragment;
  2 +
  3 +import androidx.databinding.DataBindingUtil;
  4 +import androidx.databinding.ViewDataBinding;
  5 +import android.os.Bundle;
  6 +import androidx.annotation.Nullable;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  12 +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView;
  13 +
  14 +/**
  15 + * Created by Lynn on 2017/8/30.
  16 + */
  17 +
  18 +public abstract class MvpLceBindingFragment<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>, T extends ViewDataBinding> extends MvpLceFragment<CV, M, V, P> {
  19 +
  20 + public T binding;
  21 +
  22 + @Nullable
  23 + @Override
  24 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  25 + binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
  26 + return binding.getRoot();
  27 + }
  28 +
  29 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpLceFragment.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.fragment;
  2 +
  3 +import android.os.Bundle;
  4 +import androidx.annotation.CallSuper;
  5 +import androidx.annotation.NonNull;
  6 +import androidx.annotation.Nullable;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +import android.widget.Toast;
  11 +
  12 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  13 +import com.hannesdorfmann.mosby3.mvp.lce.LceAnimator;
  14 +import com.hannesdorfmann.mosby3.mvp.lce.MvpLceView;
  15 +
  16 +/**
  17 + * Created by Lynn on 2017/8/30.
  18 + */
  19 +
  20 +public abstract class MvpLceFragment<CV extends View, M, V extends MvpLceView<M>, P extends MvpPresenter<V>>
  21 + extends com.hannesdorfmann.mosby3.mvp.MvpFragment<V, P> implements MvpLceView<M> {
  22 + protected View loadingView;
  23 + protected CV contentView;
  24 + protected View errorView;
  25 +
  26 + @CallSuper
  27 + @Override
  28 + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
  29 + super.onViewCreated(view, savedInstanceState);
  30 + setUpViews(view);
  31 + }
  32 +
  33 +
  34 + @Nullable
  35 + @Override
  36 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  37 + return inflater.inflate(getLayoutId(), container, false);
  38 + }
  39 +
  40 + public void setUpViews(View view) {
  41 + loadingView = view.findViewById(loadingViewId());
  42 + contentView = view.findViewById(contentViewId());
  43 + errorView = view.findViewById(errorViewId());
  44 +
  45 + if (loadingView == null) {
  46 + throw new NullPointerException(
  47 + "Loading view is null! Have you specified a loading view in your layout xml file?");
  48 + }
  49 +
  50 + if (contentView == null) {
  51 + throw new NullPointerException(
  52 + "Content view is null! Have you specified a content view in your layout xml file?");
  53 + }
  54 +
  55 + if (errorView == null) {
  56 + throw new NullPointerException(
  57 + "Error view is null! Have you specified a error view in your layout xml file?");
  58 + }
  59 +
  60 +// errorView.setOnClickListener(new View.OnClickListener() {
  61 +// @Override
  62 +// public void onClick(View view) {
  63 +// onErrorViewClicked();
  64 +// }
  65 +// });
  66 + }
  67 +
  68 +
  69 + @NonNull
  70 + public abstract int loadingViewId();
  71 +
  72 + @NonNull
  73 + public abstract int contentViewId();
  74 +
  75 + @NonNull
  76 + public abstract int errorViewId();
  77 +
  78 + public abstract int getLayoutId();
  79 +
  80 +
  81 + @Override
  82 + public void showLoading(boolean pullToRefresh) {
  83 + if (!pullToRefresh) {
  84 + animateLoadingViewIn();
  85 + }
  86 + }
  87 +
  88 + protected void animateLoadingViewIn() {
  89 + LceAnimator.showLoading(loadingView, contentView, errorView);
  90 + }
  91 +
  92 + @Override
  93 + public void showContent() {
  94 + animateContentViewIn();
  95 + }
  96 +
  97 + protected void animateContentViewIn() {
  98 + LceAnimator.showContent(loadingView, contentView, errorView);
  99 + }
  100 +
  101 + protected abstract String getErrorMessage(Throwable e, boolean pullToRefresh);
  102 +
  103 + protected void showLightError(String msg) {
  104 + if (getActivity() != null) {
  105 + Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
  106 + }
  107 + }
  108 +
  109 +// protected void onErrorViewClicked() {
  110 +// loadData(false);
  111 +// }
  112 +
  113 + @Override
  114 + public void showError(Throwable e, boolean pullToRefresh) {
  115 + String errorMsg = getErrorMessage(e, pullToRefresh);
  116 + if (pullToRefresh) {
  117 + showLightError(errorMsg);
  118 + } else {
  119 + animateErrorViewIn();
  120 + }
  121 + }
  122 +
  123 + protected void animateErrorViewIn() {
  124 + LceAnimator.showErrorView(loadingView, contentView, errorView);
  125 + }
  126 +
  127 + @Override
  128 + public void onDestroyView() {
  129 + super.onDestroyView();
  130 + loadingView = null;
  131 + contentView = null;
  132 + errorView.setOnClickListener(null);
  133 + errorView = null;
  134 + }
  135 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/fragment/MvpViewStateFragment.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.fragment;
  2 +
  3 +import android.os.Bundle;
  4 +import android.os.Parcelable;
  5 +import androidx.annotation.NonNull;
  6 +import androidx.annotation.Nullable;
  7 +import android.view.LayoutInflater;
  8 +import android.view.View;
  9 +import android.view.ViewGroup;
  10 +
  11 +import com.cnlive.libs.base.frame.ReflectUtil;
  12 +import com.cnlive.libs.base.frame.state.MvpViewState;
  13 +import com.cnlive.libs.base.frame.view.MvpStateView;
  14 +import com.hannesdorfmann.mosby3.mvp.MvpPresenter;
  15 +
  16 +/**
  17 + * Created by xiansong on 2017/8/29.
  18 + */
  19 +
  20 +public abstract class MvpViewStateFragment<V extends MvpStateView<D>, P extends MvpPresenter<V>, D extends Parcelable> extends com.hannesdorfmann.mosby3.mvp.viewstate.MvpViewStateFragment<V, P, MvpViewState<V, D>> {
  21 +
  22 + public V view;
  23 + public MvpViewState<V, D> viewState;
  24 +
  25 + protected abstract int getLayoutId();
  26 +
  27 + @Override
  28 + @Nullable
  29 + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  30 + return inflater.inflate(getLayoutId(), container, false);
  31 + }
  32 +
  33 + @NonNull
  34 + public V createView() {
  35 + return ReflectUtil.instance(0, this.getClass(), this);
  36 + }
  37 +
  38 + @Override
  39 + @NonNull
  40 + public P createPresenter() {
  41 + return ReflectUtil.instance(1, this);
  42 + }
  43 +
  44 + protected D initLayoutData() {
  45 + return ReflectUtil.instance(2, this);
  46 + }
  47 +
  48 + protected MvpViewState<V, D> initViewState() {
  49 + return new MvpViewState<>(initLayoutData());
  50 + }
  51 +
  52 + @Override
  53 + @NonNull
  54 + public MvpViewState<V, D> createViewState() {
  55 + if (viewState == null) {
  56 + viewState = initViewState();
  57 + }
  58 + return viewState;
  59 + }
  60 +
  61 + @NonNull
  62 + public D getViewData() {
  63 + return getViewState().getViewData();
  64 + }
  65 +
  66 + @Override
  67 + @NonNull
  68 + public V getMvpView() {
  69 + if (view == null) {
  70 + view = createView();
  71 + }
  72 + return view;
  73 + }
  74 +}
0 \ No newline at end of file 75 \ No newline at end of file
lib_media/src/main/java/com/cnlive/libs/base/frame/state/MvpViewState.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.state;
  2 +
  3 +import android.os.Bundle;
  4 +import android.os.Parcelable;
  5 +
  6 +import androidx.annotation.NonNull;
  7 +
  8 +import com.cnlive.libs.base.frame.view.MvpStateView;
  9 +import com.hannesdorfmann.mosby3.mvp.viewstate.RestorableViewState;
  10 +
  11 +/**
  12 + * Created by xiansong on 2017/8/28.
  13 + */
  14 +
  15 +public class MvpViewState<V extends MvpStateView<D>, D extends Parcelable> implements RestorableViewState<V> {
  16 +
  17 + private static final String key_data = "state-data";
  18 +
  19 + protected D data;
  20 +
  21 + public MvpViewState(D data) {
  22 + this.data = data;
  23 + }
  24 +
  25 + @NonNull
  26 + public D getViewData() {
  27 + return data;
  28 + }
  29 +
  30 + @Override
  31 + public void saveInstanceState(@NonNull Bundle out) {
  32 + out.putParcelable(key_data, data);
  33 + }
  34 +
  35 + @Override
  36 + public RestorableViewState<V> restoreInstanceState(Bundle in) {
  37 + if (in == null) return null;
  38 + data = in.getParcelable(key_data);
  39 + return this;
  40 + }
  41 +
  42 + @Override
  43 + public void apply(V view, boolean retained) {
  44 + view.onRestoreDataComplete(data);
  45 + }
  46 +
  47 +
  48 +}
lib_media/src/main/java/com/cnlive/libs/base/frame/view/MvpStateView.java 0 → 100644
  1 +package com.cnlive.libs.base.frame.view;
  2 +
  3 +import com.hannesdorfmann.mosby3.mvp.MvpView;
  4 +
  5 +/**
  6 + * Created by xiansong on 2017/8/28.
  7 + */
  8 +
  9 +public interface MvpStateView<D> extends MvpView {
  10 + void onRestoreDataComplete(D data);
  11 +}
lib_media/src/main/java/com/cnlive/libs/base/util/AlertUtil.java 0 → 100644
  1 +package com.cnlive.libs.base.util;
  2 +
  3 +import android.content.Context;
  4 +import android.view.Gravity;
  5 +import android.widget.Toast;
  6 +
  7 +import com.cnlive.media.R;
  8 +
  9 +/**
  10 + * Created by xiansong on 2017/9/11.
  11 + */
  12 +
  13 +public class AlertUtil {
  14 +
  15 + public static void showDeftToast(Context context, int messageRes) {
  16 + Toast.makeText(context,context.getString(messageRes),Toast.LENGTH_SHORT).show();
  17 + }
  18 +
  19 + public static void showDeftToast(Context context, String message) {
  20 + Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
  21 + }
  22 +
  23 + public static void showLongToast(Context context, String message, int duration){
  24 + Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
  25 + }
  26 +
  27 + /**
  28 + * 成功的提示
  29 + *
  30 + * @param context
  31 + * @param message
  32 + */
  33 + public static void showSuccessToast(Context context, String message) {
  34 + Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
  35 + }
  36 +
  37 + /**
  38 + * 失败的提示
  39 + *
  40 + * @param context
  41 + * @param message
  42 + */
  43 + public static void showFailedToast(Context context, String message) {
  44 + Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
  45 + }
  46 +
  47 + /**
  48 + * 不比较吐司内容是否相同提示
  49 + *
  50 + * @param context
  51 + * @param message
  52 + */
  53 + public static void showNoEqulesToast(Context context, String message) {
  54 + Toast.makeText(context,message,Toast.LENGTH_SHORT).show();
  55 + }
  56 +}
lib_media/src/main/java/com/cnlive/libs/base/util/DoublePressed.java 0 → 100644
  1 +package com.cnlive.libs.base.util;
  2 +
  3 +public class DoublePressed {
  4 + private static long time_pressed;
  5 + private static long upload_time;
  6 +
  7 + /**
  8 + * 连续点击处理
  9 + *
  10 + * @return
  11 + */
  12 + public static boolean onDoublePressed() {
  13 + return onDoublePressed(false, 2000L);
  14 + }
  15 +
  16 + public static boolean onLongDoublePressed() {
  17 + return onDoublePressed(true, 2000L);
  18 + }
  19 +
  20 + public static boolean onDoublePressed(boolean isLong, long time) {
  21 + long timeMillis = System.currentTimeMillis();
  22 + boolean doublePressed = time_pressed + time > timeMillis;
  23 +
  24 + if (isLong) {
  25 + time_pressed = timeMillis;
  26 + } else if (upload_time < timeMillis) {
  27 + upload_time = timeMillis + time;
  28 + time_pressed = timeMillis;
  29 + }
  30 +
  31 + return doublePressed;
  32 + }
  33 +
  34 + public static void onRestart() {
  35 + time_pressed = 0;
  36 + upload_time = 0;
  37 + }
  38 +}
lib_media/src/main/java/com/cnlive/libs/base/util/FileUtils.java 0 → 100644
  1 +package com.cnlive.libs.base.util;
  2 +
  3 +import android.content.Context;
  4 +import android.os.Environment;
  5 +
  6 +import java.io.BufferedInputStream;
  7 +import java.io.BufferedOutputStream;
  8 +import java.io.File;
  9 +import java.io.FileFilter;
  10 +import java.io.FileInputStream;
  11 +import java.io.FileNotFoundException;
  12 +import java.io.FileOutputStream;
  13 +import java.io.IOException;
  14 +import java.io.InputStream;
  15 +import java.io.OutputStream;
  16 +import java.net.HttpURLConnection;
  17 +import java.net.URL;
  18 +import java.security.DigestInputStream;
  19 +import java.security.MessageDigest;
  20 +import java.security.NoSuchAlgorithmException;
  21 +import java.util.ArrayList;
  22 +import java.util.List;
  23 +import java.util.Locale;
  24 +/**
  25 + * 作者: 吴奎庆
  26 + * <p>
  27 + * 时间: 2018/9/11
  28 + * <p>
  29 + * 简介:
  30 + */
  31 +
  32 +public class FileUtils {
  33 +
  34 + private static final String LINE_SEP = System.getProperty("line.separator");
  35 +
  36 + private FileUtils() {
  37 + throw new UnsupportedOperationException("u can't instantiate me...");
  38 + }
  39 +
  40 + /**
  41 + * Return the file by path.
  42 + *
  43 + * @param filePath The path of file.
  44 + * @return the file
  45 + */
  46 + public static File getFileByPath(final String filePath) {
  47 + return isSpace(filePath) ? null : new File(filePath);
  48 + }
  49 +
  50 + /**
  51 + * Return whether the file exists.
  52 + *
  53 + * @param filePath The path of file.
  54 + * @return {@code true}: yes<br>{@code false}: no
  55 + */
  56 + public static boolean isFileExists(final String filePath) {
  57 + return isFileExists(getFileByPath(filePath));
  58 + }
  59 +
  60 + /**
  61 + * Return whether the file exists.
  62 + *
  63 + * @param file The file.
  64 + * @return {@code true}: yes<br>{@code false}: no
  65 + */
  66 + public static boolean isFileExists(final File file) {
  67 + return file != null && file.exists();
  68 + }
  69 +
  70 + /**
  71 + * Rename the file.
  72 + *
  73 + * @param filePath The path of file.
  74 + * @param newName The new name of file.
  75 + * @return {@code true}: success<br>{@code false}: fail
  76 + */
  77 + public static boolean rename(final String filePath, final String newName) {
  78 + return rename(getFileByPath(filePath), newName);
  79 + }
  80 +
  81 + /**
  82 + * Rename the file.
  83 + *
  84 + * @param file The file.
  85 + * @param newName The new name of file.
  86 + * @return {@code true}: success<br>{@code false}: fail
  87 + */
  88 + public static boolean rename(final File file, final String newName) {
  89 + // file is null then return false
  90 + if (file == null) return false;
  91 + // file doesn't exist then return false
  92 + if (!file.exists()) return false;
  93 + // the new name is space then return false
  94 + if (isSpace(newName)) return false;
  95 + // the new name equals old name then return true
  96 + if (newName.equals(file.getName())) return true;
  97 + File newFile = new File(file.getParent() + File.separator + newName);
  98 + // the new name of file exists then return false
  99 + return !newFile.exists()
  100 + && file.renameTo(newFile);
  101 + }
  102 +
  103 + /**
  104 + * Return whether it is a directory.
  105 + *
  106 + * @param dirPath The path of directory.
  107 + * @return {@code true}: yes<br>{@code false}: no
  108 + */
  109 + public static boolean isDir(final String dirPath) {
  110 + return isDir(getFileByPath(dirPath));
  111 + }
  112 +
  113 + /**
  114 + * Return whether it is a directory.
  115 + *
  116 + * @param file The file.
  117 + * @return {@code true}: yes<br>{@code false}: no
  118 + */
  119 + public static boolean isDir(final File file) {
  120 + return file != null && file.exists() && file.isDirectory();
  121 + }
  122 +
  123 + /**
  124 + * Return whether it is a file.
  125 + *
  126 + * @param filePath The path of file.
  127 + * @return {@code true}: yes<br>{@code false}: no
  128 + */
  129 + public static boolean isFile(final String filePath) {
  130 + return isFile(getFileByPath(filePath));
  131 + }
  132 +
  133 + /**
  134 + * Return whether it is a file.
  135 + *
  136 + * @param file The file.
  137 + * @return {@code true}: yes<br>{@code false}: no
  138 + */
  139 + public static boolean isFile(final File file) {
  140 + return file != null && file.exists() && file.isFile();
  141 + }
  142 +
  143 + /**
  144 + * Create a directory if it doesn't exist, otherwise do nothing.
  145 + * 如果不存在创建文件夹 存在就不处理
  146 + * @param dirPath The path of directory.
  147 + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise
  148 + */
  149 + public static boolean createOrExistsDir(final String dirPath) {
  150 + return createOrExistsDir(getFileByPath(dirPath));
  151 + }
  152 +
  153 + /**
  154 + * Create a directory if it doesn't exist, otherwise do nothing.
  155 + *
  156 + * @param file The file.
  157 + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise
  158 + */
  159 + public static boolean createOrExistsDir(final File file) {
  160 + return file != null && (file.exists() ? file.isDirectory() : file.mkdirs());
  161 + }
  162 +
  163 + /**
  164 + * Create a file if it doesn't exist, otherwise do nothing.
  165 + *
  166 + * @param filePath The path of file.
  167 + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise
  168 + */
  169 + public static boolean createOrExistsFile(final String filePath) {
  170 + return createOrExistsFile(getFileByPath(filePath));
  171 + }
  172 +
  173 + /**
  174 + * Create a file if it doesn't exist, otherwise do nothing.
  175 + *
  176 + * @param file The file.
  177 + * @return {@code true}: exists or creates successfully<br>{@code false}: otherwise
  178 + */
  179 + public static boolean createOrExistsFile(final File file) {
  180 + if (file == null) return false;
  181 + if (file.exists()) return file.isFile();
  182 + if (!createOrExistsDir(file.getParentFile())) return false;
  183 + try {
  184 + return file.createNewFile();
  185 + } catch (IOException e) {
  186 + e.printStackTrace();
  187 + return false;
  188 + }
  189 + }
  190 +
  191 + /**
  192 + * Create a file if it doesn't exist, otherwise delete old file before creating.
  193 + *
  194 + * @param filePath The path of file.
  195 + * @return {@code true}: success<br>{@code false}: fail
  196 + */
  197 + public static boolean createFileByDeleteOldFile(final String filePath) {
  198 + return createFileByDeleteOldFile(getFileByPath(filePath));
  199 + }
  200 +
  201 + /**
  202 + * Create a file if it doesn't exist, otherwise delete old file before creating.
  203 + *
  204 + * @param file The file.
  205 + * @return {@code true}: success<br>{@code false}: fail
  206 + */
  207 + public static boolean createFileByDeleteOldFile(final File file) {
  208 + if (file == null) return false;
  209 + // file exists and unsuccessfully delete then return false
  210 + if (file.exists() && !file.delete()) return false;
  211 + if (!createOrExistsDir(file.getParentFile())) return false;
  212 + try {
  213 + return file.createNewFile();
  214 + } catch (IOException e) {
  215 + e.printStackTrace();
  216 + return false;
  217 + }
  218 + }
  219 +
  220 + /**
  221 + * Copy the directory.
  222 + *
  223 + * @param srcDirPath The path of source directory.
  224 + * @param destDirPath The path of destination directory.
  225 + * @return {@code true}: success<br>{@code false}: fail
  226 + */
  227 + public static boolean copyDir(final String srcDirPath,
  228 + final String destDirPath) {
  229 + return copyDir(getFileByPath(srcDirPath), getFileByPath(destDirPath));
  230 + }
  231 +
  232 + /**
  233 + * Copy the directory.
  234 + *
  235 + * @param srcDirPath The path of source directory.
  236 + * @param destDirPath The path of destination directory.
  237 + * @param listener The replace listener.
  238 + * @return {@code true}: success<br>{@code false}: fail
  239 + */
  240 + public static boolean copyDir(final String srcDirPath,
  241 + final String destDirPath,
  242 + final OnReplaceListener listener) {
  243 + return copyDir(getFileByPath(srcDirPath), getFileByPath(destDirPath), listener);
  244 + }
  245 +
  246 + /**
  247 + * Copy the directory.
  248 + *
  249 + * @param srcDir The source directory.
  250 + * @param destDir The destination directory.
  251 + * @return {@code true}: success<br>{@code false}: fail
  252 + */
  253 + public static boolean copyDir(final File srcDir,
  254 + final File destDir) {
  255 + return copyOrMoveDir(srcDir, destDir, false);
  256 + }
  257 +
  258 + /**
  259 + * Copy the directory.
  260 + *
  261 + * @param srcDir The source directory.
  262 + * @param destDir The destination directory.
  263 + * @param listener The replace listener.
  264 + * @return {@code true}: success<br>{@code false}: fail
  265 + */
  266 + public static boolean copyDir(final File srcDir,
  267 + final File destDir,
  268 + final OnReplaceListener listener) {
  269 + return copyOrMoveDir(srcDir, destDir, listener, false);
  270 + }
  271 +
  272 + /**
  273 + * Copy the file.
  274 + *
  275 + * @param srcFilePath The path of source file.
  276 + * @param destFilePath The path of destination file.
  277 + * @return {@code true}: success<br>{@code false}: fail
  278 + */
  279 + public static boolean copyFile(final String srcFilePath,
  280 + final String destFilePath) {
  281 + return copyFile(getFileByPath(srcFilePath), getFileByPath(destFilePath));
  282 + }
  283 +
  284 + /**
  285 + * Copy the file.
  286 + *
  287 + * @param srcFilePath The path of source file.
  288 + * @param destFilePath The path of destination file.
  289 + * @param listener The replace listener.
  290 + * @return {@code true}: success<br>{@code false}: fail
  291 + */
  292 + public static boolean copyFile(final String srcFilePath,
  293 + final String destFilePath,
  294 + final OnReplaceListener listener) {
  295 + return copyFile(getFileByPath(srcFilePath), getFileByPath(destFilePath), listener);
  296 + }
  297 +
  298 + /**
  299 + * Copy the file.
  300 + *
  301 + * @param srcFile The source file.
  302 + * @param destFile The destination file.
  303 + * @return {@code true}: success<br>{@code false}: fail
  304 + */
  305 + public static boolean copyFile(final File srcFile,
  306 + final File destFile) {
  307 + return copyOrMoveFile(srcFile, destFile, false);
  308 + }
  309 +
  310 +
  311 + public static File getSaveFile(Context context, String fileName) {
  312 + File file = new File(context.getFilesDir(), fileName + ".jpg");
  313 + return file;
  314 + }
  315 +
  316 + /**
  317 + * Copy the file.
  318 + *
  319 + * @param srcFile The source file.
  320 + * @param destFile The destination file.
  321 + * @param listener The replace listener.
  322 + * @return {@code true}: success<br>{@code false}: fail
  323 + */
  324 + public static boolean copyFile(final File srcFile,
  325 + final File destFile,
  326 + final OnReplaceListener listener) {
  327 + return copyOrMoveFile(srcFile, destFile, listener, false);
  328 + }
  329 +
  330 + /**
  331 + * Move the directory.
  332 + *
  333 + * @param srcDirPath The path of source directory.
  334 + * @param destDirPath The path of destination directory.
  335 + * @return {@code true}: success<br>{@code false}: fail
  336 + */
  337 + public static boolean moveDir(final String srcDirPath,
  338 + final String destDirPath) {
  339 + return moveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath));
  340 + }
  341 +
  342 + /**
  343 + * Move the directory.
  344 + *
  345 + * @param srcDirPath The path of source directory.
  346 + * @param destDirPath The path of destination directory.
  347 + * @param listener The replace listener.
  348 + * @return {@code true}: success<br>{@code false}: fail
  349 + */
  350 + public static boolean moveDir(final String srcDirPath,
  351 + final String destDirPath,
  352 + final OnReplaceListener listener) {
  353 + return moveDir(getFileByPath(srcDirPath), getFileByPath(destDirPath), listener);
  354 + }
  355 +
  356 + /**
  357 + * Move the directory.
  358 + *
  359 + * @param srcDir The source directory.
  360 + * @param destDir The destination directory.
  361 + * @return {@code true}: success<br>{@code false}: fail
  362 + */
  363 + public static boolean moveDir(final File srcDir,
  364 + final File destDir) {
  365 + return copyOrMoveDir(srcDir, destDir, true);
  366 + }
  367 +
  368 + /**
  369 + * Move the directory.
  370 + *
  371 + * @param srcDir The source directory.
  372 + * @param destDir The destination directory.
  373 + * @param listener The replace listener.
  374 + * @return {@code true}: success<br>{@code false}: fail
  375 + */
  376 + public static boolean moveDir(final File srcDir,
  377 + final File destDir,
  378 + final OnReplaceListener listener) {
  379 + return copyOrMoveDir(srcDir, destDir, listener, true);
  380 + }
  381 +
  382 + /**
  383 + * Move the file.
  384 + *
  385 + * @param srcFilePath The path of source file.
  386 + * @param destFilePath The path of destination file.
  387 + * @return {@code true}: success<br>{@code false}: fail
  388 + */
  389 + public static boolean moveFile(final String srcFilePath,
  390 + final String destFilePath) {
  391 + return moveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath));
  392 + }
  393 +
  394 + /**
  395 + * Move the file.
  396 + *
  397 + * @param srcFilePath The path of source file.
  398 + * @param destFilePath The path of destination file.
  399 + * @param listener The replace listener.
  400 + * @return {@code true}: success<br>{@code false}: fail
  401 + */
  402 + public static boolean moveFile(final String srcFilePath,
  403 + final String destFilePath,
  404 + final OnReplaceListener listener) {
  405 + return moveFile(getFileByPath(srcFilePath), getFileByPath(destFilePath), listener);
  406 + }
  407 +
  408 + /**
  409 + * Move the file.
  410 + *
  411 + * @param srcFile The source file.
  412 + * @param destFile The destination file.
  413 + * @return {@code true}: success<br>{@code false}: fail
  414 + */
  415 + public static boolean moveFile(final File srcFile,
  416 + final File destFile) {
  417 + return copyOrMoveFile(srcFile, destFile, true);
  418 + }
  419 +
  420 + /**
  421 + * Move the file.
  422 + *
  423 + * @param srcFile The source file.
  424 + * @param destFile The destination file.
  425 + * @param listener The replace listener.
  426 + * @return {@code true}: success<br>{@code false}: fail
  427 + */
  428 + public static boolean moveFile(final File srcFile,
  429 + final File destFile,
  430 + final OnReplaceListener listener) {
  431 + return copyOrMoveFile(srcFile, destFile, listener, true);
  432 + }
  433 +
  434 + private static boolean copyOrMoveDir(final File srcDir,
  435 + final File destDir,
  436 + final boolean isMove) {
  437 + return copyOrMoveDir(srcDir, destDir, new OnReplaceListener() {
  438 + @Override
  439 + public boolean onReplace() {
  440 + return true;
  441 + }
  442 + }, isMove);
  443 + }
  444 +
  445 + private static boolean copyOrMoveDir(final File srcDir,
  446 + final File destDir,
  447 + final OnReplaceListener listener,
  448 + final boolean isMove) {
  449 + if (srcDir == null || destDir == null) return false;
  450 + // destDir's path locate in srcDir's path then return false
  451 + String srcPath = srcDir.getPath() + File.separator;
  452 + String destPath = destDir.getPath() + File.separator;
  453 + if (destPath.contains(srcPath)) return false;
  454 + if (!srcDir.exists() || !srcDir.isDirectory()) return false;
  455 + if (destDir.exists()) {
  456 + if (listener == null || listener.onReplace()) {// require delete the old directory
  457 + if (!deleteAllInDir(destDir)) {// unsuccessfully delete then return false
  458 + return false;
  459 + }
  460 + } else {
  461 + return true;
  462 + }
  463 + }
  464 + if (!createOrExistsDir(destDir)) return false;
  465 + File[] files = srcDir.listFiles();
  466 + for (File file : files) {
  467 + File oneDestFile = new File(destPath + file.getName());
  468 + if (file.isFile()) {
  469 + if (!copyOrMoveFile(file, oneDestFile, listener, isMove)) return false;
  470 + } else if (file.isDirectory()) {
  471 + if (!copyOrMoveDir(file, oneDestFile, listener, isMove)) return false;
  472 + }
  473 + }
  474 + return !isMove || deleteDir(srcDir);
  475 + }
  476 +
  477 + private static boolean copyOrMoveFile(final File srcFile,
  478 + final File destFile,
  479 + final boolean isMove) {
  480 + return copyOrMoveFile(srcFile, destFile, new OnReplaceListener() {
  481 + @Override
  482 + public boolean onReplace() {
  483 + return true;
  484 + }
  485 + }, isMove);
  486 + }
  487 +
  488 + private static boolean copyOrMoveFile(final File srcFile,
  489 + final File destFile,
  490 + final OnReplaceListener listener,
  491 + final boolean isMove) {
  492 + if (srcFile == null || destFile == null) return false;
  493 + // srcFile equals destFile then return false
  494 + if (srcFile.equals(destFile)) return false;
  495 + // srcFile doesn't exist or isn't a file then return false
  496 + if (!srcFile.exists() || !srcFile.isFile()) return false;
  497 + if (destFile.exists()) {
  498 + if (listener == null || listener.onReplace()) {// require delete the old file
  499 + if (!destFile.delete()) {// unsuccessfully delete then return false
  500 + return false;
  501 + }
  502 + } else {
  503 + return true;
  504 + }
  505 + }
  506 + if (!createOrExistsDir(destFile.getParentFile())) return false;
  507 + try {
  508 + return writeFileFromIS(destFile, new FileInputStream(srcFile))
  509 + && !(isMove && !deleteFile(srcFile));
  510 + } catch (FileNotFoundException e) {
  511 + e.printStackTrace();
  512 + return false;
  513 + }
  514 + }
  515 +
  516 + /**
  517 + * Delete the directory.
  518 + *
  519 + * @param dirPath The path of directory.
  520 + * @return {@code true}: success<br>{@code false}: fail
  521 + */
  522 + public static boolean deleteDir(final String dirPath) {
  523 + return deleteDir(getFileByPath(dirPath));
  524 + }
  525 +
  526 + /**
  527 + * Delete the directory.
  528 + *
  529 + * @param dir The directory.
  530 + * @return {@code true}: success<br>{@code false}: fail
  531 + */
  532 + public static boolean deleteDir(final File dir) {
  533 + if (dir == null) return false;
  534 + // dir doesn't exist then return true
  535 + if (!dir.exists()) return true;
  536 + // dir isn't a directory then return false
  537 + if (!dir.isDirectory()) return false;
  538 + File[] files = dir.listFiles();
  539 + if (files != null && files.length != 0) {
  540 + for (File file : files) {
  541 + if (file.isFile()) {
  542 + if (!file.delete()) return false;
  543 + } else if (file.isDirectory()) {
  544 + if (!deleteDir(file)) return false;
  545 + }
  546 + }
  547 + }
  548 + return dir.delete();
  549 + }
  550 +
  551 + /**
  552 + * Delete the file.
  553 + *
  554 + * @param srcFilePath The path of source file.
  555 + * @return {@code true}: success<br>{@code false}: fail
  556 + */
  557 + public static boolean deleteFile(final String srcFilePath) {
  558 + return deleteFile(getFileByPath(srcFilePath));
  559 + }
  560 +
  561 + /**
  562 + * Delete the file.
  563 + *
  564 + * @param file The file.
  565 + * @return {@code true}: success<br>{@code false}: fail
  566 + */
  567 + public static boolean deleteFile(final File file) {
  568 + return file != null && (!file.exists() || file.isFile() && file.delete());
  569 + }
  570 +
  571 + /**
  572 + * Delete the all in directory.
  573 + *
  574 + * @param dirPath The path of directory.
  575 + * @return {@code true}: success<br>{@code false}: fail
  576 + */
  577 + public static boolean deleteAllInDir(final String dirPath) {
  578 + return deleteAllInDir(getFileByPath(dirPath));
  579 + }
  580 +
  581 + /**
  582 + * Delete the all in directory.
  583 + *
  584 + * @param dir The directory.
  585 + * @return {@code true}: success<br>{@code false}: fail
  586 + */
  587 + public static boolean deleteAllInDir(final File dir) {
  588 + return deleteFilesInDirWithFilter(dir, new FileFilter() {
  589 + @Override
  590 + public boolean accept(File pathname) {
  591 + return true;
  592 + }
  593 + });
  594 + }
  595 +
  596 + /**
  597 + * Delete all files in directory.
  598 + *
  599 + * @param dirPath The path of directory.
  600 + * @return {@code true}: success<br>{@code false}: fail
  601 + */
  602 + public static boolean deleteFilesInDir(final String dirPath) {
  603 + return deleteFilesInDir(getFileByPath(dirPath));
  604 + }
  605 +
  606 + /**
  607 + * Delete all files in directory.
  608 + *
  609 + * @param dir The directory.
  610 + * @return {@code true}: success<br>{@code false}: fail
  611 + */
  612 + public static boolean deleteFilesInDir(final File dir) {
  613 + return deleteFilesInDirWithFilter(dir, new FileFilter() {
  614 + @Override
  615 + public boolean accept(File pathname) {
  616 + return pathname.isFile();
  617 + }
  618 + });
  619 + }
  620 +
  621 + /**
  622 + * Delete all files that satisfy the filter in directory.
  623 + *
  624 + * @param dirPath The path of directory.
  625 + * @param filter The filter.
  626 + * @return {@code true}: success<br>{@code false}: fail
  627 + */
  628 + public static boolean deleteFilesInDirWithFilter(final String dirPath,
  629 + final FileFilter filter) {
  630 + return deleteFilesInDirWithFilter(getFileByPath(dirPath), filter);
  631 + }
  632 +
  633 + /**
  634 + * Delete all files that satisfy the filter in directory.
  635 + *
  636 + * @param dir The directory.
  637 + * @param filter The filter.
  638 + * @return {@code true}: success<br>{@code false}: fail
  639 + */
  640 + public static boolean deleteFilesInDirWithFilter(final File dir, final FileFilter filter) {
  641 + if (dir == null) return false;
  642 + // dir doesn't exist then return true
  643 + if (!dir.exists()) return true;
  644 + // dir isn't a directory then return false
  645 + if (!dir.isDirectory()) return false;
  646 + File[] files = dir.listFiles();
  647 + if (files != null && files.length != 0) {
  648 + for (File file : files) {
  649 + if (filter.accept(file)) {
  650 + if (file.isFile()) {
  651 + if (!file.delete()) return false;
  652 + } else if (file.isDirectory()) {
  653 + if (!deleteDir(file)) return false;
  654 + }
  655 + }
  656 + }
  657 + }
  658 + return true;
  659 + }
  660 +
  661 + /**
  662 + * Return the files in directory.
  663 + * <p>Doesn't traverse subdirectories</p>
  664 + *
  665 + * @param dirPath The path of directory.
  666 + * @return the files in directory
  667 + */
  668 + public static List<File> listFilesInDir(final String dirPath) {
  669 + return listFilesInDir(dirPath, false);
  670 + }
  671 +
  672 + /**
  673 + * Return the files in directory.
  674 + * <p>Doesn't traverse subdirectories</p>
  675 + *
  676 + * @param dir The directory.
  677 + * @return the files in directory
  678 + */
  679 + public static List<File> listFilesInDir(final File dir) {
  680 + return listFilesInDir(dir, false);
  681 + }
  682 +
  683 + /**
  684 + * Return the files in directory.
  685 + *
  686 + * @param dirPath The path of directory.
  687 + * @param isRecursive True to traverse subdirectories, false otherwise.
  688 + * @return the files in directory
  689 + */
  690 + public static List<File> listFilesInDir(final String dirPath, final boolean isRecursive) {
  691 + return listFilesInDir(getFileByPath(dirPath), isRecursive);
  692 + }
  693 +
  694 + /**
  695 + * Return the files in directory.
  696 + *
  697 + * @param dir The directory.
  698 + * @param isRecursive True to traverse subdirectories, false otherwise.
  699 + * @return the files in directory
  700 + */
  701 + public static List<File> listFilesInDir(final File dir, final boolean isRecursive) {
  702 + return listFilesInDirWithFilter(dir, new FileFilter() {
  703 + @Override
  704 + public boolean accept(File pathname) {
  705 + return true;
  706 + }
  707 + }, isRecursive);
  708 + }
  709 +
  710 + /**
  711 + * Return the files that satisfy the filter in directory.
  712 + * <p>Doesn't traverse subdirectories</p>
  713 + *
  714 + * @param dirPath The path of directory.
  715 + * @param filter The filter.
  716 + * @return the files that satisfy the filter in directory
  717 + */
  718 + public static List<File> listFilesInDirWithFilter(final String dirPath,
  719 + final FileFilter filter) {
  720 + return listFilesInDirWithFilter(getFileByPath(dirPath), filter, false);
  721 + }
  722 +
  723 + /**
  724 + * Return the files that satisfy the filter in directory.
  725 + * <p>Doesn't traverse subdirectories</p>
  726 + *
  727 + * @param dir The directory.
  728 + * @param filter The filter.
  729 + * @return the files that satisfy the filter in directory
  730 + */
  731 + public static List<File> listFilesInDirWithFilter(final File dir,
  732 + final FileFilter filter) {
  733 + return listFilesInDirWithFilter(dir, filter, false);
  734 + }
  735 +
  736 + /**
  737 + * Return the files that satisfy the filter in directory.
  738 + *
  739 + * @param dirPath The path of directory.
  740 + * @param filter The filter.
  741 + * @param isRecursive True to traverse subdirectories, false otherwise.
  742 + * @return the files that satisfy the filter in directory
  743 + */
  744 + public static List<File> listFilesInDirWithFilter(final String dirPath,
  745 + final FileFilter filter,
  746 + final boolean isRecursive) {
  747 + return listFilesInDirWithFilter(getFileByPath(dirPath), filter, isRecursive);
  748 + }
  749 +
  750 + /**
  751 + * Return the files that satisfy the filter in directory.
  752 + *
  753 + * @param dir The directory.
  754 + * @param filter The filter.
  755 + * @param isRecursive True to traverse subdirectories, false otherwise.
  756 + * @return the files that satisfy the filter in directory
  757 + */
  758 + public static List<File> listFilesInDirWithFilter(final File dir,
  759 + final FileFilter filter,
  760 + final boolean isRecursive) {
  761 + if (!isDir(dir)) return null;
  762 + List<File> list = new ArrayList<>();
  763 + File[] files = dir.listFiles();
  764 + if (files != null && files.length != 0) {
  765 + for (File file : files) {
  766 + if (filter.accept(file)) {
  767 + list.add(file);
  768 + }
  769 + if (isRecursive && file.isDirectory()) {
  770 + //noinspection ConstantConditions
  771 + list.addAll(listFilesInDirWithFilter(file, filter, true));
  772 + }
  773 + }
  774 + }
  775 + return list;
  776 + }
  777 +
  778 + /**
  779 + * Return the time that the file was last modified.
  780 + *
  781 + * @param filePath The path of file.
  782 + * @return the time that the file was last modified
  783 + */
  784 +
  785 + public static long getFileLastModified(final String filePath) {
  786 + return getFileLastModified(getFileByPath(filePath));
  787 + }
  788 +
  789 + /**
  790 + * Return the time that the file was last modified.
  791 + *
  792 + * @param file The file.
  793 + * @return the time that the file was last modified
  794 + */
  795 + public static long getFileLastModified(final File file) {
  796 + if (file == null) return -1;
  797 + return file.lastModified();
  798 + }
  799 +
  800 + /**
  801 + * Return the charset of file simply.
  802 + *
  803 + * @param filePath The path of file.
  804 + * @return the charset of file simply
  805 + */
  806 + public static String getFileCharsetSimple(final String filePath) {
  807 + return getFileCharsetSimple(getFileByPath(filePath));
  808 + }
  809 +
  810 + /**
  811 + * Return the charset of file simply.
  812 + *
  813 + * @param file The file.
  814 + * @return the charset of file simply
  815 + */
  816 + public static String getFileCharsetSimple(final File file) {
  817 + int p = 0;
  818 + InputStream is = null;
  819 + try {
  820 + is = new BufferedInputStream(new FileInputStream(file));
  821 + p = (is.read() << 8) + is.read();
  822 + } catch (IOException e) {
  823 + e.printStackTrace();
  824 + } finally {
  825 + try {
  826 + if (is != null) {
  827 + is.close();
  828 + }
  829 + } catch (IOException e) {
  830 + e.printStackTrace();
  831 + }
  832 + }
  833 + switch (p) {
  834 + case 0xefbb:
  835 + return "UTF-8";
  836 + case 0xfffe:
  837 + return "Unicode";
  838 + case 0xfeff:
  839 + return "UTF-16BE";
  840 + default:
  841 + return "GBK";
  842 + }
  843 + }
  844 +
  845 + /**
  846 + * Return the number of lines of file.
  847 + *
  848 + * @param filePath The path of file.
  849 + * @return the number of lines of file
  850 + */
  851 + public static int getFileLines(final String filePath) {
  852 + return getFileLines(getFileByPath(filePath));
  853 + }
  854 +
  855 + /**
  856 + * Return the number of lines of file.
  857 + *
  858 + * @param file The file.
  859 + * @return the number of lines of file
  860 + */
  861 + public static int getFileLines(final File file) {
  862 + int count = 1;
  863 + InputStream is = null;
  864 + try {
  865 + is = new BufferedInputStream(new FileInputStream(file));
  866 + byte[] buffer = new byte[1024];
  867 + int readChars;
  868 + if (LINE_SEP.endsWith("\n")) {
  869 + while ((readChars = is.read(buffer, 0, 1024)) != -1) {
  870 + for (int i = 0; i < readChars; ++i) {
  871 + if (buffer[i] == '\n') ++count;
  872 + }
  873 + }
  874 + } else {
  875 + while ((readChars = is.read(buffer, 0, 1024)) != -1) {
  876 + for (int i = 0; i < readChars; ++i) {
  877 + if (buffer[i] == '\r') ++count;
  878 + }
  879 + }
  880 + }
  881 + } catch (IOException e) {
  882 + e.printStackTrace();
  883 + } finally {
  884 + try {
  885 + if (is != null) {
  886 + is.close();
  887 + }
  888 + } catch (IOException e) {
  889 + e.printStackTrace();
  890 + }
  891 + }
  892 + return count;
  893 + }
  894 +
  895 + /**
  896 + * Return the size of directory.
  897 + *
  898 + * @param dirPath The path of directory.
  899 + * @return the size of directory
  900 + */
  901 + public static String getDirSize(final String dirPath) {
  902 + return getDirSize(getFileByPath(dirPath));
  903 + }
  904 +
  905 + /**
  906 + * Return the size of directory.
  907 + *
  908 + * @param dir The directory.
  909 + * @return the size of directory
  910 + */
  911 + public static String getDirSize(final File dir) {
  912 + long len = getDirLength(dir);
  913 + return len == -1 ? "" : byte2FitMemorySize(len);
  914 + }
  915 +
  916 + /**
  917 + * Return the length of file.
  918 + *
  919 + * @param filePath The path of file.
  920 + * @return the length of file
  921 + */
  922 + public static String getFileSize(final String filePath) {
  923 + long len = getFileLength(filePath);
  924 + return len == -1 ? "" : byte2FitMemorySize(len);
  925 + }
  926 +
  927 + /**
  928 + * Return the length of file.
  929 + *
  930 + * @param file The file.
  931 + * @return the length of file
  932 + */
  933 + public static String getFileSize(final File file) {
  934 + long len = getFileLength(file);
  935 + return len == -1 ? "" : byte2FitMemorySize(len);
  936 + }
  937 +
  938 + /**
  939 + * Return the length of directory.
  940 + *
  941 + * @param dirPath The path of directory.
  942 + * @return the length of directory
  943 + */
  944 + public static long getDirLength(final String dirPath) {
  945 + return getDirLength(getFileByPath(dirPath));
  946 + }
  947 +
  948 + /**
  949 + * Return the length of directory.
  950 + *
  951 + * @param dir The directory.
  952 + * @return the length of directory
  953 + */
  954 + public static long getDirLength(final File dir) {
  955 + if (!isDir(dir)) return -1;
  956 + long len = 0;
  957 + File[] files = dir.listFiles();
  958 + if (files != null && files.length != 0) {
  959 + for (File file : files) {
  960 + if (file.isDirectory()) {
  961 + len += getDirLength(file);
  962 + } else {
  963 + len += file.length();
  964 + }
  965 + }
  966 + }
  967 + return len;
  968 + }
  969 +
  970 + /**
  971 + * Return the length of file.
  972 + *
  973 + * @param filePath The path of file.
  974 + * @return the length of file
  975 + */
  976 + public static long getFileLength(final String filePath) {
  977 + boolean isURL = filePath.matches("[a-zA-z]+://[^\\s]*");
  978 + if (isURL) {
  979 + try {
  980 + HttpURLConnection conn = (HttpURLConnection) new URL(filePath).openConnection();
  981 + conn.setRequestProperty("Accept-Encoding", "identity");
  982 + conn.connect();
  983 + if (conn.getResponseCode() == 200) {
  984 + return conn.getContentLength();
  985 + }
  986 + return -1;
  987 + } catch (IOException e) {
  988 + e.printStackTrace();
  989 + }
  990 + }
  991 + return getFileLength(getFileByPath(filePath));
  992 + }
  993 +
  994 + /**
  995 + * Return the length of file.
  996 + *
  997 + * @param file The file.
  998 + * @return the length of file
  999 + */
  1000 + public static long getFileLength(final File file) {
  1001 + if (!isFile(file)) return -1;
  1002 + return file.length();
  1003 + }
  1004 +
  1005 + /**
  1006 + * Return the MD5 of file.
  1007 + *
  1008 + * @param filePath The path of file.
  1009 + * @return the md5 of file
  1010 + */
  1011 + public static String getFileMD5ToString(final String filePath) {
  1012 + File file = isSpace(filePath) ? null : new File(filePath);
  1013 + return getFileMD5ToString(file);
  1014 + }
  1015 +
  1016 + /**
  1017 + * Return the MD5 of file.
  1018 + *
  1019 + * @param file The file.
  1020 + * @return the md5 of file
  1021 + */
  1022 + public static String getFileMD5ToString(final File file) {
  1023 + return bytes2HexString(getFileMD5(file));
  1024 + }
  1025 +
  1026 + /**
  1027 + * Return the MD5 of file.
  1028 + *
  1029 + * @param filePath The path of file.
  1030 + * @return the md5 of file
  1031 + */
  1032 + public static byte[] getFileMD5(final String filePath) {
  1033 + return getFileMD5(getFileByPath(filePath));
  1034 + }
  1035 +
  1036 + /**
  1037 + * Return the MD5 of file.
  1038 + *
  1039 + * @param file The file.
  1040 + * @return the md5 of file
  1041 + */
  1042 + public static byte[] getFileMD5(final File file) {
  1043 + if (file == null) return null;
  1044 + DigestInputStream dis = null;
  1045 + try {
  1046 + FileInputStream fis = new FileInputStream(file);
  1047 + MessageDigest md = MessageDigest.getInstance("MD5");
  1048 + dis = new DigestInputStream(fis, md);
  1049 + byte[] buffer = new byte[1024 * 256];
  1050 + while (true) {
  1051 + if (!(dis.read(buffer) > 0)) break;
  1052 + }
  1053 + md = dis.getMessageDigest();
  1054 + return md.digest();
  1055 + } catch (NoSuchAlgorithmException | IOException e) {
  1056 + e.printStackTrace();
  1057 + } finally {
  1058 + try {
  1059 + if (dis != null) {
  1060 + dis.close();
  1061 + }
  1062 + } catch (IOException e) {
  1063 + e.printStackTrace();
  1064 + }
  1065 + }
  1066 + return null;
  1067 + }
  1068 +
  1069 + /**
  1070 + * Return the file's path of directory.
  1071 + *
  1072 + * @param file The file.
  1073 + * @return the file's path of directory
  1074 + */
  1075 + public static String getDirName(final File file) {
  1076 + if (file == null) return "";
  1077 + return getDirName(file.getAbsolutePath());
  1078 + }
  1079 +
  1080 + /**
  1081 + * Return the file's path of directory.
  1082 + *
  1083 + * @param filePath The path of file.
  1084 + * @return the file's path of directory
  1085 + */
  1086 + public static String getDirName(final String filePath) {
  1087 + if (isSpace(filePath)) return "";
  1088 + int lastSep = filePath.lastIndexOf(File.separator);
  1089 + return lastSep == -1 ? "" : filePath.substring(0, lastSep + 1);
  1090 + }
  1091 +
  1092 + /**
  1093 + * Return the name of file.
  1094 + *
  1095 + * @param file The file.
  1096 + * @return the name of file
  1097 + */
  1098 + public static String getFileName(final File file) {
  1099 + if (file == null) return "";
  1100 + return getFileName(file.getAbsolutePath());
  1101 + }
  1102 +
  1103 + /**
  1104 + * Return the name of file.
  1105 + *
  1106 + * @param filePath The path of file.
  1107 + * @return the name of file
  1108 + */
  1109 + public static String getFileName(final String filePath) {
  1110 + if (isSpace(filePath)) return "";
  1111 + int lastSep = filePath.lastIndexOf(File.separator);
  1112 + return lastSep == -1 ? filePath : filePath.substring(lastSep + 1);
  1113 + }
  1114 +
  1115 + /**
  1116 + * Return the name of file without extension.
  1117 + *
  1118 + * @param file The file.
  1119 + * @return the name of file without extension
  1120 + */
  1121 + public static String getFileNameNoExtension(final File file) {
  1122 + if (file == null) return "";
  1123 + return getFileNameNoExtension(file.getPath());
  1124 + }
  1125 +
  1126 + /**
  1127 + * Return the name of file without extension.
  1128 + *
  1129 + * @param filePath The path of file.
  1130 + * @return the name of file without extension
  1131 + */
  1132 + public static String getFileNameNoExtension(final String filePath) {
  1133 + if (isSpace(filePath)) return "";
  1134 + int lastPoi = filePath.lastIndexOf('.');
  1135 + int lastSep = filePath.lastIndexOf(File.separator);
  1136 + if (lastSep == -1) {
  1137 + return (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi));
  1138 + }
  1139 + if (lastPoi == -1 || lastSep > lastPoi) {
  1140 + return filePath.substring(lastSep + 1);
  1141 + }
  1142 + return filePath.substring(lastSep + 1, lastPoi);
  1143 + }
  1144 +
  1145 + /**
  1146 + * Return the extension of file.
  1147 + *
  1148 + * @param file The file.
  1149 + * @return the extension of file
  1150 + */
  1151 + public static String getFileExtension(final File file) {
  1152 + if (file == null) return "";
  1153 + return getFileExtension(file.getPath());
  1154 + }
  1155 +
  1156 + /**
  1157 + * Return the extension of file.
  1158 + *
  1159 + * @param filePath The path of file.
  1160 + * @return the extension of file
  1161 + */
  1162 + public static String getFileExtension(final String filePath) {
  1163 + if (isSpace(filePath)) return "";
  1164 + int lastPoi = filePath.lastIndexOf('.');
  1165 + int lastSep = filePath.lastIndexOf(File.separator);
  1166 + if (lastPoi == -1 || lastSep >= lastPoi) return "";
  1167 + return filePath.substring(lastPoi + 1);
  1168 + }
  1169 +
  1170 + ///////////////////////////////////////////////////////////////////////////
  1171 + // interface
  1172 + ///////////////////////////////////////////////////////////////////////////
  1173 +
  1174 + public interface OnReplaceListener {
  1175 + boolean onReplace();
  1176 + }
  1177 +
  1178 + ///////////////////////////////////////////////////////////////////////////
  1179 + // other utils methods
  1180 + ///////////////////////////////////////////////////////////////////////////
  1181 +
  1182 + private static final char HEX_DIGITS[] =
  1183 + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  1184 +
  1185 + private static String bytes2HexString(final byte[] bytes) {
  1186 + if (bytes == null) return "";
  1187 + int len = bytes.length;
  1188 + if (len <= 0) return "";
  1189 + char[] ret = new char[len << 1];
  1190 + for (int i = 0, j = 0; i < len; i++) {
  1191 + ret[j++] = HEX_DIGITS[bytes[i] >> 4 & 0x0f];
  1192 + ret[j++] = HEX_DIGITS[bytes[i] & 0x0f];
  1193 + }
  1194 + return new String(ret);
  1195 + }
  1196 +
  1197 + private static String byte2FitMemorySize(final long byteNum) {
  1198 + if (byteNum < 0) {
  1199 + return "shouldn't be less than zero!";
  1200 + } else if (byteNum < 1024) {
  1201 + return String.format(Locale.getDefault(), "%.3fB", (double) byteNum);
  1202 + } else if (byteNum < 1048576) {
  1203 + return String.format(Locale.getDefault(), "%.3fKB", (double) byteNum / 1024);
  1204 + } else if (byteNum < 1073741824) {
  1205 + return String.format(Locale.getDefault(), "%.3fMB", (double) byteNum / 1048576);
  1206 + } else {
  1207 + return String.format(Locale.getDefault(), "%.3fGB", (double) byteNum / 1073741824);
  1208 + }
  1209 + }
  1210 +
  1211 + private static boolean isSpace(final String s) {
  1212 + if (s == null) return true;
  1213 + for (int i = 0, len = s.length(); i < len; ++i) {
  1214 + if (!Character.isWhitespace(s.charAt(i))) {
  1215 + return false;
  1216 + }
  1217 + }
  1218 + return true;
  1219 + }
  1220 +
  1221 + private static boolean writeFileFromIS(final File file,
  1222 + final InputStream is) {
  1223 + OutputStream os = null;
  1224 + try {
  1225 + os = new BufferedOutputStream(new FileOutputStream(file));
  1226 + byte data[] = new byte[8192];
  1227 + int len;
  1228 + while ((len = is.read(data, 0, 8192)) != -1) {
  1229 + os.write(data, 0, len);
  1230 + }
  1231 + return true;
  1232 + } catch (IOException e) {
  1233 + e.printStackTrace();
  1234 + return false;
  1235 + } finally {
  1236 + try {
  1237 + is.close();
  1238 + } catch (IOException e) {
  1239 + e.printStackTrace();
  1240 + }
  1241 + try {
  1242 + if (os != null) {
  1243 + os.close();
  1244 + }
  1245 + } catch (IOException e) {
  1246 + e.printStackTrace();
  1247 + }
  1248 + }
  1249 + }
  1250 +
  1251 + public static boolean isExternalStorageWritable() {
  1252 + String state = Environment.getExternalStorageState();
  1253 + if (Environment.MEDIA_MOUNTED.equals(state)) {
  1254 + return true;
  1255 + }
  1256 + return false;
  1257 + }
  1258 +
  1259 +}
lib_media/src/main/java/com/cnlive/libs/base/util/StatusBarUtil2.java 0 → 100644
  1 +package com.cnlive.libs.base.util;
  2 +
  3 +import android.annotation.TargetApi;
  4 +import android.app.Activity;
  5 +import android.content.Context;
  6 +import android.graphics.Color;
  7 +import android.os.Build;
  8 +import androidx.annotation.ColorInt;
  9 +import androidx.annotation.IntRange;
  10 +import androidx.annotation.NonNull;
  11 +import androidx.coordinatorlayout.widget.CoordinatorLayout;
  12 +import androidx.drawerlayout.widget.DrawerLayout;
  13 +import android.view.View;
  14 +import android.view.ViewGroup;
  15 +import android.view.Window;
  16 +import android.view.WindowManager;
  17 +import android.widget.LinearLayout;
  18 +
  19 +
  20 +import com.cnlive.media.R;
  21 +import com.qiniu.pili.droid.shortvideo.PLShortVideoEnv;
  22 +
  23 +import java.lang.reflect.Field;
  24 +import java.lang.reflect.Method;
  25 +
  26 +/**
  27 + * Created by Jaeger on 16/2/14.
  28 + * <p>
  29 + * Email: chjie.jaeger@gmail.com
  30 + * GitHub: https://github.com/laobie
  31 + */
  32 +public class StatusBarUtil2 {
  33 +
  34 + public static final int DEFAULT_STATUS_BAR_ALPHA = 112;
  35 + private static final int FAKE_STATUS_BAR_VIEW_ID = R.id.status_bar_util_fake_status_bar_view;
  36 + private static final int FAKE_TRANSLUCENT_VIEW_ID = R.id.status_bar_util_translucent_view;
  37 + private static final int TAG_KEY_HAVE_SET_OFFSET = -123;
  38 +
  39 + /**
  40 + * 设置状态栏颜色
  41 + *
  42 + * @param activity 需要设置的 activity
  43 + * @param color 状态栏颜色值
  44 + */
  45 + public static void setColor(Activity activity, @ColorInt int color) {
  46 + setColor(activity, color, DEFAULT_STATUS_BAR_ALPHA);
  47 + PLShortVideoEnv.init()
  48 + }
  49 +
  50 + /**
  51 + * 设置状态栏颜色
  52 + *
  53 + * @param activity 需要设置的activity
  54 + * @param color 状态栏颜色值
  55 + * @param statusBarAlpha 状态栏透明度
  56 + */
  57 +
  58 + public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  59 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  60 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  61 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  62 + activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha));
  63 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  64 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  65 + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
  66 + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  67 + if (fakeStatusBarView != null) {
  68 + if (fakeStatusBarView.getVisibility() == View.GONE) {
  69 + fakeStatusBarView.setVisibility(View.VISIBLE);
  70 + }
  71 + fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
  72 + } else {
  73 + decorView.addView(createStatusBarView(activity, color, statusBarAlpha));
  74 + }
  75 + setRootView(activity);
  76 + }
  77 + }
  78 +
  79 + /**
  80 + * 为滑动返回界面设置状态栏颜色
  81 + *
  82 + * @param activity 需要设置的activity
  83 + * @param color 状态栏颜色值
  84 + */
  85 + public static void setColorForSwipeBack(Activity activity, int color) {
  86 + setColorForSwipeBack(activity, color, DEFAULT_STATUS_BAR_ALPHA);
  87 + }
  88 +
  89 + /**
  90 + * 为滑动返回界面设置状态栏颜色
  91 + *
  92 + * @param activity 需要设置的activity
  93 + * @param color 状态栏颜色值
  94 + * @param statusBarAlpha 状态栏透明度
  95 + */
  96 + public static void setColorForSwipeBack(Activity activity, @ColorInt int color,
  97 + @IntRange(from = 0, to = 255) int statusBarAlpha) {
  98 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  99 +
  100 + ViewGroup contentView = ((ViewGroup) activity.findViewById(android.R.id.content));
  101 + View rootView = contentView.getChildAt(0);
  102 + int statusBarHeight = getStatusBarHeight(activity);
  103 + if (rootView != null && rootView instanceof CoordinatorLayout) {
  104 + final CoordinatorLayout coordinatorLayout = (CoordinatorLayout) rootView;
  105 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
  106 + coordinatorLayout.setFitsSystemWindows(false);
  107 + contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
  108 + boolean isNeedRequestLayout = contentView.getPaddingTop() < statusBarHeight;
  109 + if (isNeedRequestLayout) {
  110 + contentView.setPadding(0, statusBarHeight, 0, 0);
  111 + coordinatorLayout.post(new Runnable() {
  112 + @Override
  113 + public void run() {
  114 + coordinatorLayout.requestLayout();
  115 + }
  116 + });
  117 + }
  118 + } else {
  119 + coordinatorLayout.setStatusBarBackgroundColor(calculateStatusColor(color, statusBarAlpha));
  120 + }
  121 + } else {
  122 + contentView.setPadding(0, statusBarHeight, 0, 0);
  123 + contentView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
  124 + }
  125 + setTransparentForWindow(activity);
  126 + }
  127 + }
  128 +
  129 + /**
  130 + * 设置状态栏纯色 不加半透明效果
  131 + *
  132 + * @param activity 需要设置的 activity
  133 + * @param color 状态栏颜色值
  134 + */
  135 + public static void setColorNoTranslucent(Activity activity, @ColorInt int color) {
  136 + setColor(activity, color, 0);
  137 + }
  138 +
  139 + /**
  140 + * 设置状态栏颜色(5.0以下无半透明效果,不建议使用)
  141 + *
  142 + * @param activity 需要设置的 activity
  143 + * @param color 状态栏颜色值
  144 + */
  145 + @Deprecated
  146 + public static void setColorDiff(Activity activity, @ColorInt int color) {
  147 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  148 + return;
  149 + }
  150 + transparentStatusBar(activity);
  151 + ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
  152 + // 移除半透明矩形,以免叠加
  153 + View fakeStatusBarView = contentView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  154 + if (fakeStatusBarView != null) {
  155 + if (fakeStatusBarView.getVisibility() == View.GONE) {
  156 + fakeStatusBarView.setVisibility(View.VISIBLE);
  157 + }
  158 + fakeStatusBarView.setBackgroundColor(color);
  159 + } else {
  160 + contentView.addView(createStatusBarView(activity, color));
  161 + }
  162 + setRootView(activity);
  163 + }
  164 +
  165 + /**
  166 + * 使状态栏半透明
  167 + * <p>
  168 + * 适用于图片作为背景的界面,此时需要图片填充到状态栏
  169 + *
  170 + * @param activity 需要设置的activity
  171 + */
  172 + public static void setTranslucent(Activity activity) {
  173 + setTranslucent(activity, DEFAULT_STATUS_BAR_ALPHA);
  174 + }
  175 +
  176 + /**
  177 + * 使状态栏半透明
  178 + * <p>
  179 + * 适用于图片作为背景的界面,此时需要图片填充到状态栏
  180 + *
  181 + * @param activity 需要设置的activity
  182 + * @param statusBarAlpha 状态栏透明度
  183 + */
  184 + public static void setTranslucent(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  185 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  186 + return;
  187 + }
  188 + setTransparent(activity);
  189 + addTranslucentView(activity, statusBarAlpha);
  190 + }
  191 +
  192 + /**
  193 + * 针对根布局是 CoordinatorLayout, 使状态栏半透明
  194 + * <p>
  195 + * 适用于图片作为背景的界面,此时需要图片填充到状态栏
  196 + *
  197 + * @param activity 需要设置的activity
  198 + * @param statusBarAlpha 状态栏透明度
  199 + */
  200 + public static void setTranslucentForCoordinatorLayout(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  201 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  202 + return;
  203 + }
  204 + transparentStatusBar(activity);
  205 + addTranslucentView(activity, statusBarAlpha);
  206 + }
  207 +
  208 + /**
  209 + * 设置状态栏全透明
  210 + *
  211 + * @param activity 需要设置的activity
  212 + */
  213 + public static void setTransparent(Activity activity) {
  214 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  215 + return;
  216 + }
  217 + transparentStatusBar(activity);
  218 + setRootView(activity);
  219 + }
  220 +
  221 + /**
  222 + * 使状态栏透明(5.0以上半透明效果,不建议使用)
  223 + * <p>
  224 + * 适用于图片作为背景的界面,此时需要图片填充到状态栏
  225 + *
  226 + * @param activity 需要设置的activity
  227 + */
  228 + @Deprecated
  229 + public static void setTranslucentDiff(Activity activity) {
  230 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  231 + // 设置状态栏透明
  232 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  233 + setRootView(activity);
  234 + }
  235 + }
  236 +
  237 + /**
  238 + * 为DrawerLayout 布局设置状态栏变色
  239 + *
  240 + * @param activity 需要设置的activity
  241 + * @param drawerLayout DrawerLayout
  242 + * @param color 状态栏颜色值
  243 + */
  244 + public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
  245 + setColorForDrawerLayout(activity, drawerLayout, color, DEFAULT_STATUS_BAR_ALPHA);
  246 + }
  247 +
  248 + /**
  249 + * 为DrawerLayout 布局设置状态栏颜色,纯色
  250 + *
  251 + * @param activity 需要设置的activity
  252 + * @param drawerLayout DrawerLayout
  253 + * @param color 状态栏颜色值
  254 + */
  255 + public static void setColorNoTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
  256 + setColorForDrawerLayout(activity, drawerLayout, color, 0);
  257 + }
  258 +
  259 + /**
  260 + * 为DrawerLayout 布局设置状态栏变色
  261 + *
  262 + * @param activity 需要设置的activity
  263 + * @param drawerLayout DrawerLayout
  264 + * @param color 状态栏颜色值
  265 + * @param statusBarAlpha 状态栏透明度
  266 + */
  267 + public static void setColorForDrawerLayout(Activity activity, DrawerLayout drawerLayout, @ColorInt int color,
  268 + @IntRange(from = 0, to = 255) int statusBarAlpha) {
  269 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  270 + return;
  271 + }
  272 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  273 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  274 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  275 + activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
  276 + } else {
  277 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  278 + }
  279 + // 生成一个状态栏大小的矩形
  280 + // 添加 statusBarView 到布局中
  281 + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
  282 + View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  283 + if (fakeStatusBarView != null) {
  284 + if (fakeStatusBarView.getVisibility() == View.GONE) {
  285 + fakeStatusBarView.setVisibility(View.VISIBLE);
  286 + }
  287 + fakeStatusBarView.setBackgroundColor(color);
  288 + } else {
  289 + contentLayout.addView(createStatusBarView(activity, color), 0);
  290 + }
  291 + // 内容布局不是 LinearLayout 时,设置padding top
  292 + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
  293 + contentLayout.getChildAt(1)
  294 + .setPadding(contentLayout.getPaddingLeft(), getStatusBarHeight(activity) + contentLayout.getPaddingTop(),
  295 + contentLayout.getPaddingRight(), contentLayout.getPaddingBottom());
  296 + }
  297 + // 设置属性
  298 + setDrawerLayoutProperty(drawerLayout, contentLayout);
  299 + addTranslucentView(activity, statusBarAlpha);
  300 + }
  301 +
  302 + /**
  303 + * 设置 DrawerLayout 属性
  304 + *
  305 + * @param drawerLayout DrawerLayout
  306 + * @param drawerLayoutContentLayout DrawerLayout 的内容布局
  307 + */
  308 + private static void setDrawerLayoutProperty(DrawerLayout drawerLayout, ViewGroup drawerLayoutContentLayout) {
  309 + ViewGroup drawer = (ViewGroup) drawerLayout.getChildAt(1);
  310 + drawerLayout.setFitsSystemWindows(false);
  311 + drawerLayoutContentLayout.setFitsSystemWindows(false);
  312 + drawerLayoutContentLayout.setClipToPadding(true);
  313 + drawer.setFitsSystemWindows(false);
  314 + }
  315 +
  316 + /**
  317 + * 为DrawerLayout 布局设置状态栏变色(5.0以下无半透明效果,不建议使用)
  318 + *
  319 + * @param activity 需要设置的activity
  320 + * @param drawerLayout DrawerLayout
  321 + * @param color 状态栏颜色值
  322 + */
  323 + @Deprecated
  324 + public static void setColorForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout, @ColorInt int color) {
  325 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  326 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  327 + // 生成一个状态栏大小的矩形
  328 + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
  329 + View fakeStatusBarView = contentLayout.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  330 + if (fakeStatusBarView != null) {
  331 + if (fakeStatusBarView.getVisibility() == View.GONE) {
  332 + fakeStatusBarView.setVisibility(View.VISIBLE);
  333 + }
  334 + fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, DEFAULT_STATUS_BAR_ALPHA));
  335 + } else {
  336 + // 添加 statusBarView 到布局中
  337 + contentLayout.addView(createStatusBarView(activity, color), 0);
  338 + }
  339 + // 内容布局不是 LinearLayout 时,设置padding top
  340 + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
  341 + contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
  342 + }
  343 + // 设置属性
  344 + setDrawerLayoutProperty(drawerLayout, contentLayout);
  345 + }
  346 + }
  347 +
  348 + /**
  349 + * 为 DrawerLayout 布局设置状态栏透明
  350 + *
  351 + * @param activity 需要设置的activity
  352 + * @param drawerLayout DrawerLayout
  353 + */
  354 + public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
  355 + setTranslucentForDrawerLayout(activity, drawerLayout, DEFAULT_STATUS_BAR_ALPHA);
  356 + }
  357 +
  358 + /**
  359 + * 为 DrawerLayout 布局设置状态栏透明
  360 + *
  361 + * @param activity 需要设置的activity
  362 + * @param drawerLayout DrawerLayout
  363 + */
  364 + public static void setTranslucentForDrawerLayout(Activity activity, DrawerLayout drawerLayout,
  365 + @IntRange(from = 0, to = 255) int statusBarAlpha) {
  366 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  367 + return;
  368 + }
  369 + setTransparentForDrawerLayout(activity, drawerLayout);
  370 + addTranslucentView(activity, statusBarAlpha);
  371 + }
  372 +
  373 + /**
  374 + * 为 DrawerLayout 布局设置状态栏透明
  375 + *
  376 + * @param activity 需要设置的activity
  377 + * @param drawerLayout DrawerLayout
  378 + */
  379 + public static void setTransparentForDrawerLayout(Activity activity, DrawerLayout drawerLayout) {
  380 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  381 + return;
  382 + }
  383 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  384 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  385 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  386 + activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
  387 + } else {
  388 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  389 + }
  390 +
  391 + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
  392 + // 内容布局不是 LinearLayout 时,设置padding top
  393 + if (!(contentLayout instanceof LinearLayout) && contentLayout.getChildAt(1) != null) {
  394 + contentLayout.getChildAt(1).setPadding(0, getStatusBarHeight(activity), 0, 0);
  395 + }
  396 +
  397 + // 设置属性
  398 + setDrawerLayoutProperty(drawerLayout, contentLayout);
  399 + }
  400 +
  401 + /**
  402 + * 为 DrawerLayout 布局设置状态栏透明(5.0以上半透明效果,不建议使用)
  403 + *
  404 + * @param activity 需要设置的activity
  405 + * @param drawerLayout DrawerLayout
  406 + */
  407 + @Deprecated
  408 + public static void setTranslucentForDrawerLayoutDiff(Activity activity, DrawerLayout drawerLayout) {
  409 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  410 + // 设置状态栏透明
  411 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  412 + // 设置内容布局属性
  413 + ViewGroup contentLayout = (ViewGroup) drawerLayout.getChildAt(0);
  414 + contentLayout.setFitsSystemWindows(true);
  415 + contentLayout.setClipToPadding(true);
  416 + // 设置抽屉布局属性
  417 + ViewGroup vg = (ViewGroup) drawerLayout.getChildAt(1);
  418 + vg.setFitsSystemWindows(false);
  419 + // 设置 DrawerLayout 属性
  420 + drawerLayout.setFitsSystemWindows(false);
  421 + }
  422 + }
  423 +
  424 + /**
  425 + * 为头部是 ImageView 的界面设置状态栏全透明
  426 + *
  427 + * @param activity 需要设置的activity
  428 + * @param needOffsetView 需要向下偏移的 View
  429 + */
  430 + public static void setTransparentForImageView(Activity activity, View needOffsetView) {
  431 + setTranslucentForImageView(activity, 0, needOffsetView);
  432 + }
  433 +
  434 + /**
  435 + * 为头部是 ImageView 的界面设置状态栏透明(使用默认透明度)
  436 + *
  437 + * @param activity 需要设置的activity
  438 + * @param needOffsetView 需要向下偏移的 View
  439 + */
  440 + public static void setTranslucentForImageView(Activity activity, View needOffsetView) {
  441 + setTranslucentForImageView(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
  442 + }
  443 +
  444 + /**
  445 + * 为头部是 ImageView 的界面设置状态栏透明
  446 + *
  447 + * @param activity 需要设置的activity
  448 + * @param statusBarAlpha 状态栏透明度
  449 + * @param needOffsetView 需要向下偏移的 View
  450 + */
  451 + public static void setTranslucentForImageView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
  452 + View needOffsetView) {
  453 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  454 + return;
  455 + }
  456 + setTransparentForWindow(activity);
  457 + addTranslucentView(activity, statusBarAlpha);
  458 + if (needOffsetView != null) {
  459 + Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET);
  460 + if (haveSetOffset != null && (Boolean) haveSetOffset) {
  461 + return;
  462 + }
  463 + ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams();
  464 + layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity),
  465 + layoutParams.rightMargin, layoutParams.bottomMargin);
  466 + needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true);
  467 + }
  468 + }
  469 +
  470 + /**
  471 + * 为 fragment 头部是 ImageView 的设置状态栏透明
  472 + *
  473 + * @param activity fragment 对应的 activity
  474 + * @param needOffsetView 需要向下偏移的 View
  475 + */
  476 + public static void setTranslucentForImageViewInFragment(Activity activity, View needOffsetView) {
  477 + setTranslucentForImageViewInFragment(activity, DEFAULT_STATUS_BAR_ALPHA, needOffsetView);
  478 + }
  479 +
  480 + /**
  481 + * 为 fragment 头部是 ImageView 的设置状态栏透明
  482 + *
  483 + * @param activity fragment 对应的 activity
  484 + * @param needOffsetView 需要向下偏移的 View
  485 + */
  486 + public static void setTransparentForImageViewInFragment(Activity activity, View needOffsetView) {
  487 + setTranslucentForImageViewInFragment(activity, 0, needOffsetView);
  488 + }
  489 +
  490 + /**
  491 + * 为 fragment 头部是 ImageView 的设置状态栏透明
  492 + *
  493 + * @param activity fragment 对应的 activity
  494 + * @param statusBarAlpha 状态栏透明度
  495 + * @param needOffsetView 需要向下偏移的 View
  496 + */
  497 + public static void setTranslucentForImageViewInFragment(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha,
  498 + View needOffsetView) {
  499 + setTranslucentForImageView(activity, statusBarAlpha, needOffsetView);
  500 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
  501 + clearPreviousSetting(activity);
  502 + }
  503 + }
  504 +
  505 + /**
  506 + * 隐藏伪状态栏 View
  507 + *
  508 + * @param activity 调用的 Activity
  509 + */
  510 + public static void hideFakeStatusBarView(Activity activity) {
  511 + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
  512 + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  513 + if (fakeStatusBarView != null) {
  514 + fakeStatusBarView.setVisibility(View.GONE);
  515 + }
  516 + View fakeTranslucentView = decorView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
  517 + if (fakeTranslucentView != null) {
  518 + fakeTranslucentView.setVisibility(View.GONE);
  519 + }
  520 + }
  521 +
  522 + @TargetApi(Build.VERSION_CODES.M)
  523 + public static void setLightMode(Activity activity) {
  524 + setMIUIStatusBarDarkIcon(activity, true);
  525 + setMeizuStatusBarDarkIcon(activity, true);
  526 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  527 + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
  528 + }
  529 + }
  530 +
  531 + @TargetApi(Build.VERSION_CODES.M)
  532 + public static void setDarkMode(Activity activity) {
  533 + setMIUIStatusBarDarkIcon(activity, false);
  534 + setMeizuStatusBarDarkIcon(activity, false);
  535 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  536 + activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
  537 + }
  538 + }
  539 +
  540 + /**
  541 + * 修改 MIUI V6 以上状态栏颜色
  542 + */
  543 + private static void setMIUIStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
  544 + Class<? extends Window> clazz = activity.getWindow().getClass();
  545 + try {
  546 + Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
  547 + Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
  548 + int darkModeFlag = field.getInt(layoutParams);
  549 + Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
  550 + extraFlagField.invoke(activity.getWindow(), darkIcon ? darkModeFlag : 0, darkModeFlag);
  551 + } catch (Exception e) {
  552 + //e.printStackTrace();
  553 + }
  554 + }
  555 +
  556 + /**
  557 + * 修改魅族状态栏字体颜色 Flyme 4.0
  558 + */
  559 + private static void setMeizuStatusBarDarkIcon(@NonNull Activity activity, boolean darkIcon) {
  560 + try {
  561 + WindowManager.LayoutParams lp = activity.getWindow().getAttributes();
  562 + Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
  563 + Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
  564 + darkFlag.setAccessible(true);
  565 + meizuFlags.setAccessible(true);
  566 + int bit = darkFlag.getInt(null);
  567 + int value = meizuFlags.getInt(lp);
  568 + if (darkIcon) {
  569 + value |= bit;
  570 + } else {
  571 + value &= ~bit;
  572 + }
  573 + meizuFlags.setInt(lp, value);
  574 + activity.getWindow().setAttributes(lp);
  575 + } catch (Exception e) {
  576 + //e.printStackTrace();
  577 + }
  578 + }
  579 +
  580 + ///////////////////////////////////////////////////////////////////////////////////
  581 +
  582 + @TargetApi(Build.VERSION_CODES.KITKAT)
  583 + private static void clearPreviousSetting(Activity activity) {
  584 + ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
  585 + View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID);
  586 + if (fakeStatusBarView != null) {
  587 + decorView.removeView(fakeStatusBarView);
  588 + ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
  589 + rootView.setPadding(0, 0, 0, 0);
  590 + }
  591 + }
  592 +
  593 + /**
  594 + * 添加半透明矩形条
  595 + *
  596 + * @param activity 需要设置的 activity
  597 + * @param statusBarAlpha 透明值
  598 + */
  599 + public static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) {
  600 + ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
  601 + View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID);
  602 + if (fakeTranslucentView != null) {
  603 + if (fakeTranslucentView.getVisibility() == View.GONE) {
  604 + fakeTranslucentView.setVisibility(View.VISIBLE);
  605 + }
  606 + fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0));
  607 + } else {
  608 + contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha));
  609 + }
  610 + }
  611 +
  612 + /**
  613 + * 生成一个和状态栏大小相同的彩色矩形条
  614 + *
  615 + * @param activity 需要设置的 activity
  616 + * @param color 状态栏颜色值
  617 + * @return 状态栏矩形条
  618 + */
  619 + private static View createStatusBarView(Activity activity, @ColorInt int color) {
  620 + return createStatusBarView(activity, color, 0);
  621 + }
  622 +
  623 + /**
  624 + * 生成一个和状态栏大小相同的半透明矩形条
  625 + *
  626 + * @param activity 需要设置的activity
  627 + * @param color 状态栏颜色值
  628 + * @param alpha 透明值
  629 + * @return 状态栏矩形条
  630 + */
  631 + private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) {
  632 + // 绘制一个和状态栏一样高的矩形
  633 + View statusBarView = new View(activity);
  634 + LinearLayout.LayoutParams params =
  635 + new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
  636 + statusBarView.setLayoutParams(params);
  637 + statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
  638 + statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);
  639 + return statusBarView;
  640 + }
  641 +
  642 + /**
  643 + * 设置根布局参数
  644 + */
  645 + private static void setRootView(Activity activity) {
  646 + ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content);
  647 + for (int i = 0, count = parent.getChildCount(); i < count; i++) {
  648 + View childView = parent.getChildAt(i);
  649 + if (childView instanceof ViewGroup) {
  650 + childView.setFitsSystemWindows(true);
  651 + ((ViewGroup) childView).setClipToPadding(true);
  652 + }
  653 + }
  654 + }
  655 +
  656 + /**
  657 + * 设置透明
  658 + */
  659 + public static void setTransparentForWindow(Activity activity) {
  660 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  661 + activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
  662 + activity.getWindow()
  663 + .getDecorView()
  664 + .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
  665 + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  666 + activity.getWindow()
  667 + .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  668 + }
  669 + }
  670 +
  671 + /**
  672 + * 使状态栏透明
  673 + */
  674 + @TargetApi(Build.VERSION_CODES.KITKAT)
  675 + private static void transparentStatusBar(Activity activity) {
  676 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  677 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  678 + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  679 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
  680 + activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
  681 + } else {
  682 + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  683 + }
  684 + }
  685 +
  686 + /**
  687 + * 创建半透明矩形 View
  688 + *
  689 + * @param alpha 透明值
  690 + * @return 半透明 View
  691 + */
  692 + private static View createTranslucentStatusBarView(Activity activity, int alpha) {
  693 + // 绘制一个和状态栏一样高的矩形
  694 + View statusBarView = new View(activity);
  695 + LinearLayout.LayoutParams params =
  696 + new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
  697 + statusBarView.setLayoutParams(params);
  698 + statusBarView.setBackgroundColor(Color.argb(alpha, 0, 0, 0));
  699 + statusBarView.setId(FAKE_TRANSLUCENT_VIEW_ID);
  700 + return statusBarView;
  701 + }
  702 +
  703 + /**
  704 + * 获取状态栏高度
  705 + *
  706 + * @param context context
  707 + * @return 状态栏高度
  708 + */
  709 + public static int getStatusBarHeight(Context context) {
  710 + // 获得状态栏高度
  711 + int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
  712 + return context.getResources().getDimensionPixelSize(resourceId);
  713 + }
  714 +
  715 + /**
  716 + * 计算状态栏颜色
  717 + *
  718 + * @param color color值
  719 + * @param alpha alpha值
  720 + * @return 最终的状态栏颜色
  721 + */
  722 + private static int calculateStatusColor(@ColorInt int color, int alpha) {
  723 + if (alpha == 0) {
  724 + return color;
  725 + }
  726 + float a = 1 - alpha / 255f;
  727 + int red = color >> 16 & 0xff;
  728 + int green = color >> 8 & 0xff;
  729 + int blue = color & 0xff;
  730 + red = (int) (red * a + 0.5);
  731 + green = (int) (green * a + 0.5);
  732 + blue = (int) (blue * a + 0.5);
  733 + return 0xff << 24 | red << 16 | green << 8 | blue;
  734 + }
  735 +}
lib_media/src/main/java/com/cnlive/libs/base/util/StringUtils.java 0 → 100644
  1 +package com.cnlive.libs.base.util;
  2 +
  3 +import android.annotation.TargetApi;
  4 +import android.nfc.NdefRecord;
  5 +import android.os.Build;
  6 +import android.text.TextPaint;
  7 +import android.util.Base64;
  8 +import android.util.Log;
  9 +
  10 +import java.net.URLDecoder;
  11 +import java.net.URLEncoder;
  12 +import java.nio.charset.Charset;
  13 +import java.text.DecimalFormat;
  14 +import java.text.SimpleDateFormat;
  15 +import java.util.ArrayList;
  16 +import java.util.Calendar;
  17 +import java.util.Date;
  18 +import java.util.Iterator;
  19 +import java.util.Locale;
  20 +import java.util.TimeZone;
  21 +import java.util.regex.Matcher;
  22 +import java.util.regex.Pattern;
  23 +
  24 +
  25 +/**
  26 + * 字符串工具类
  27 + *
  28 + * @author tangjun
  29 + */
  30 +public class StringUtils {
  31 +
  32 + public static final String EMPTY = "";
  33 + public static final SimpleDateFormat DATE_FORMAT_PART = new SimpleDateFormat(
  34 + "HH:mm", Locale.getDefault());
  35 + private static final String TAG = StringUtils.class.getSimpleName();
  36 + private static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
  37 + private static final String DEFAULT_DATETIME_PATTERN = "yyyy-MM-dd hh:mm:ss";
  38 + /**
  39 + * 用于生成文件
  40 + */
  41 + private static final String DEFAULT_FILE_PATTERN = "yyyy-MM-dd-HH-mm-ss";
  42 + private static final double KB = 1024.0;
  43 + private static final double MB = 1048576.0;
  44 + private static final double GB = 1073741824.0;
  45 +
  46 + public static String currentTimeString() {
  47 + return DATE_FORMAT_PART.format(Calendar.getInstance().getTime());
  48 + }
  49 +
  50 + public static char chatAt(String pinyin, int index) {
  51 + if (pinyin != null && pinyin.length() > 0)
  52 + return pinyin.charAt(index);
  53 + return ' ';
  54 + }
  55 +
  56 + /**
  57 + * 获取字符串宽度
  58 + */
  59 + public static float GetTextWidth(String Sentence, float Size) {
  60 + if (isEmpty(Sentence))
  61 + return 0;
  62 + TextPaint FontPaint = new TextPaint();
  63 + FontPaint.setTextSize(Size);
  64 + return FontPaint.measureText(Sentence.trim()) + (int) (Size * 0.1); // 留点余地
  65 + }
  66 +
  67 + /**
  68 + * 格式化日期字符串
  69 + *
  70 + * @param date
  71 + * @param pattern
  72 + * @return
  73 + */
  74 + public static String formatDate(Date date, String pattern) {
  75 + SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.getDefault());
  76 + return format.format(date);
  77 + }
  78 +
  79 + /**
  80 + * 格式化日期字符串
  81 + *
  82 + * @param date
  83 + * @return 例如2011-3-24
  84 + */
  85 + public static String formatDate(Date date) {
  86 + return formatDate(date, DEFAULT_DATE_PATTERN);
  87 + }
  88 +
  89 + public static String formatDate(long date) {
  90 + return formatDate(new Date(date), DEFAULT_DATE_PATTERN);
  91 + }
  92 +
  93 + /**
  94 + * 获取当前时间 格式为yyyy-MM-dd 例如2011-07-08
  95 + *
  96 + * @return
  97 + */
  98 + public static String getDate() {
  99 + return formatDate(new Date(), DEFAULT_DATE_PATTERN);
  100 + }
  101 +
  102 + /**
  103 + * 生成一个文件名,不含后缀
  104 + */
  105 + public static String createFileName() {
  106 + Date date = new Date(System.currentTimeMillis());
  107 + SimpleDateFormat format = new SimpleDateFormat(DEFAULT_FILE_PATTERN, Locale.getDefault());
  108 + return format.format(date);
  109 + }
  110 +
  111 + /**
  112 + * 获取当前时间
  113 + *
  114 + * @return
  115 + */
  116 + public static String getDateTime() {
  117 + return formatDate(new Date(), DEFAULT_DATETIME_PATTERN);
  118 + }
  119 +
  120 + /**
  121 + * 格式化日期时间字符串
  122 + *
  123 + * @param date
  124 + * @return 例如2011-11-30 16:06:54
  125 + */
  126 + public static String formatDateTime(Date date) {
  127 + return formatDate(date, DEFAULT_DATETIME_PATTERN);
  128 + }
  129 +
  130 + public static String formatDateTime(long date) {
  131 + return formatDate(new Date(date), DEFAULT_DATETIME_PATTERN);
  132 + }
  133 +
  134 + /**
  135 + * 格林威时间转换
  136 + *
  137 + * @param gmt
  138 + * @return
  139 + */
  140 + public static String formatGMTDate(String gmt) {
  141 + TimeZone timeZoneLondon = TimeZone.getTimeZone(gmt);
  142 + return formatDate(Calendar.getInstance(timeZoneLondon)
  143 + .getTimeInMillis());
  144 + }
  145 +
  146 + /**
  147 + * 拼接数组
  148 + *
  149 + * @param array
  150 + * @param separator
  151 + * @return
  152 + */
  153 + public static String join(final ArrayList<String> array,
  154 + final String separator) {
  155 + StringBuffer result = new StringBuffer();
  156 + if (array != null && array.size() > 0) {
  157 + for (String str : array) {
  158 + result.append(str);
  159 + result.append(separator);
  160 + }
  161 + result.delete(result.length() - 1, result.length());
  162 + }
  163 + return result.toString();
  164 + }
  165 +
  166 + public static String join(final Iterator<String> iter,
  167 + final String separator) {
  168 + StringBuffer result = new StringBuffer();
  169 + if (iter != null) {
  170 + while (iter.hasNext()) {
  171 + String key = iter.next();
  172 + result.append(key);
  173 + result.append(separator);
  174 + }
  175 + if (result.length() > 0)
  176 + result.delete(result.length() - 1, result.length());
  177 + }
  178 + return result.toString();
  179 + }
  180 +
  181 + /**
  182 + * 判断字符串是否为空
  183 + *
  184 + * @param str
  185 + * @return
  186 + */
  187 + public static boolean isEmpty(String str) {
  188 + return str == null || str.length() == 0 || str.equals("null");
  189 + }
  190 +
  191 + /**
  192 + * @param str
  193 + * @return
  194 + */
  195 + public static String trim(String str) {
  196 + return str == null ? EMPTY : str.trim();
  197 + }
  198 +
  199 + /**
  200 + * 转换时间显示
  201 + *
  202 + * @param time 毫秒
  203 + * @return
  204 + */
  205 + public static String generateTime(long time) {
  206 + int totalSeconds = (int) (time / 1000);
  207 + int seconds = totalSeconds % 60;
  208 + int minutes = (totalSeconds / 60) % 60;
  209 + int hours = totalSeconds / 3600;
  210 +
  211 + return hours > 0 ? String.format(Locale.getDefault(), "%02d:%02d:%02d", hours, minutes,
  212 + seconds) : String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
  213 + }
  214 +
  215 + /**
  216 + * 根据秒速获取时间格式
  217 + */
  218 + public static String gennerTime(int totalSeconds) {
  219 + int seconds = totalSeconds % 60;
  220 + int minutes = (totalSeconds / 60) % 60;
  221 + return String.format(Locale.getDefault(), "%02d:%02d", minutes, seconds);
  222 + }
  223 +
  224 + /**
  225 + * 转换文件大小
  226 + *
  227 + * @param size
  228 + * @return
  229 + */
  230 + public static String generateFileSize(long size) {
  231 + String fileSize;
  232 + if (size < KB)
  233 + fileSize = size + "B";
  234 + else if (size < MB)
  235 + fileSize = String.format("%.1f", size / KB) + "KB";
  236 + else if (size < GB)
  237 + fileSize = String.format("%.1f", size / MB) + "MB";
  238 + else
  239 + fileSize = String.format("%.1f", size / GB) + "GB";
  240 +
  241 + return fileSize;
  242 + }
  243 +
  244 + public static String getTimeDiff(long time) {
  245 + // Calendar cal = Calendar.getInstance();
  246 + long diff = 0;
  247 + // Date dnow = cal.getTime();
  248 + String str = "";
  249 + diff = System.currentTimeMillis() - time;
  250 +
  251 + if (diff > 2592000000L) {// 30 * 24 * 60 * 60 * 1000=2592000000 毫秒
  252 + str = "1个月前";
  253 + } else if (diff > 1814400000) {// 21 * 24 * 60 * 60 * 1000=1814400000 毫秒
  254 + str = "3周前";
  255 + } else if (diff > 1209600000) {// 14 * 24 * 60 * 60 * 1000=1209600000 毫秒
  256 + str = "2周前";
  257 + } else if (diff > 604800000) {// 7 * 24 * 60 * 60 * 1000=604800000 毫秒
  258 + str = "1周前";
  259 + } else if (diff > 86400000) { // 24 * 60 * 60 * 1000=86400000 毫秒
  260 + // System.out.println("X天前");
  261 + str = (int) Math.floor(diff / 86400000f) + "天前";
  262 + } else if (diff > 18000000) {// 5 * 60 * 60 * 1000=18000000 毫秒
  263 + // System.out.println("X小时前");
  264 + str = (int) Math.floor(diff / 18000000f) + "小时前";
  265 + } else if (diff > 60000) {// 1 * 60 * 1000=60000 毫秒
  266 + // System.out.println("X分钟前");
  267 + str = (int) Math.floor(diff / 60000) + "分钟前";
  268 + } else {
  269 + str = (int) Math.floor(diff / 1000) + "秒前";
  270 + }
  271 + return str;
  272 + }
  273 +
  274 + /**
  275 + * 截取字符串
  276 + *
  277 + * @param search 待搜索的字符串
  278 + * @param start 起始字符串 例如:<title>
  279 + * @param end 结束字符串 例如:</title>
  280 + * @param defaultValue
  281 + * @return
  282 + */
  283 + public static String substring(String search, String start, String end,
  284 + String defaultValue) {
  285 + int start_len = start.length();
  286 + int start_pos = StringUtils.isEmpty(start) ? 0 : search.indexOf(start);
  287 + if (start_pos > -1) {
  288 + int end_pos = StringUtils.isEmpty(end) ? -1 : search.indexOf(end,
  289 + start_pos + start_len);
  290 + if (end_pos > -1)
  291 + return search.substring(start_pos + start.length(), end_pos);
  292 + else
  293 + return search.substring(start_pos + start.length());
  294 + }
  295 + return defaultValue;
  296 + }
  297 +
  298 + /**
  299 + * 截取字符串
  300 + *
  301 + * @param search 待搜索的字符串
  302 + * @param start 起始字符串 例如:<title>
  303 + * @param end 结束字符串 例如:</title>
  304 + * @return
  305 + */
  306 + public static String substring(String search, String start, String end) {
  307 + return substring(search, start, end, "");
  308 + }
  309 +
  310 + /**
  311 + * 拼接字符串
  312 + *
  313 + * @param strs
  314 + * @return
  315 + */
  316 + public static String concat(String... strs) {
  317 + StringBuffer result = new StringBuffer();
  318 + if (strs != null) {
  319 + for (String str : strs) {
  320 + if (str != null)
  321 + result.append(str);
  322 + }
  323 + }
  324 + return result.toString();
  325 + }
  326 +
  327 + /**
  328 + * 获取中文字符个数
  329 + */
  330 + public static int getChineseCharCount(String str) {
  331 + String tempStr;
  332 + int count = 0;
  333 + for (int i = 0; i < str.length(); i++) {
  334 + tempStr = String.valueOf(str.charAt(i));
  335 + if (tempStr.getBytes().length == 3) {
  336 + count++;
  337 + }
  338 + }
  339 + return count;
  340 + }
  341 +
  342 + /**
  343 + * 获取英文字符个数
  344 + */
  345 + public static int getEnglishCount(String str) {
  346 + String tempStr;
  347 + int count = 0;
  348 + for (int i = 0; i < str.length(); i++) {
  349 + tempStr = String.valueOf(str.charAt(i));
  350 + if (!(tempStr.getBytes().length == 3)) {
  351 + count++;
  352 + }
  353 + }
  354 + return count;
  355 + }
  356 +
  357 + public static String encode(String url) {
  358 + try {
  359 + return URLEncoder.encode(url, "UTF-8");
  360 + } catch (Exception e) {
  361 + Log.e(TAG, e.getMessage(), e);
  362 + }
  363 + return url;
  364 + }
  365 +
  366 + public static String base64encode(String value) {
  367 + try {
  368 + return new String(Base64.encode(value.getBytes(), Base64.DEFAULT));
  369 + } catch (Exception e) {
  370 + Log.e(TAG, e.getMessage(), e);
  371 + }
  372 + return value;
  373 + }
  374 +
  375 + public static String decode(String url) {
  376 + try {
  377 + return URLDecoder.decode(url, "UTF-8");
  378 + } catch (Exception e) {
  379 + Log.e(TAG, e.getMessage(), e);
  380 + }
  381 + return url;
  382 + }
  383 +
  384 + public static String base64decode(String value) {
  385 + try {
  386 +
  387 + return new String(Base64.decode(value, Base64.DEFAULT));
  388 + } catch (Exception e) {
  389 + Log.e(TAG, e.getMessage(), e);
  390 + }
  391 + return value;
  392 + }
  393 +
  394 + @TargetApi(Build.VERSION_CODES.GINGERBREAD)
  395 + public static NdefRecord createTextRecord(String payload, Locale locale, boolean encodeInUtf8) {
  396 + byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
  397 + Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
  398 + byte[] textBytes = payload.getBytes(utfEncoding);
  399 + int utfBit = encodeInUtf8 ? 0 : (1 << 7);
  400 + char status = (char) (utfBit + langBytes.length);
  401 + byte[] data = new byte[1 + langBytes.length + textBytes.length];
  402 + data[0] = (byte) status;
  403 + System.arraycopy(langBytes, 0, data, 1, langBytes.length);
  404 + System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
  405 + NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
  406 + NdefRecord.RTD_TEXT, new byte[0], data);
  407 + return record;
  408 + }
  409 +
  410 + /**
  411 + * 转换中国币文字显示
  412 + *
  413 + * @param gold
  414 + * @return
  415 + */
  416 + public static String generateGoldValue(int gold) {
  417 + String goldstr;
  418 + if (gold < 10000) {
  419 + goldstr = gold + "中国币";
  420 + } else if (gold < 100000000) {
  421 + goldstr = String.format(Locale.getDefault(), "%.1f万中国币", gold / 10000);
  422 + } else
  423 + goldstr = String.format(Locale.getDefault(), "%.1f亿中国币", gold / 100000000);
  424 + return goldstr;
  425 + }
  426 +
  427 + /**
  428 + * 数量转换为万
  429 + */
  430 + public static String getNumDiff(int count, String sub) {
  431 + String afterNum = "";
  432 + if (count >= 0 && count < 10000) {
  433 + afterNum = count + sub;
  434 + } else if (count >= 10000 && count < 10000000) {
  435 + if (count / 1000 % 10 != 0) {
  436 + float num = (float) count / 10000;
  437 + DecimalFormat decimalFormat = new DecimalFormat("0.0");
  438 + afterNum = decimalFormat.format(num).concat("万" + sub);
  439 + } else {
  440 + afterNum = (count / 10000) + "万" + sub;
  441 + }
  442 + } else if (count >= 10000000) {
  443 + afterNum = "1000万" + sub;
  444 + }
  445 + return afterNum;
  446 + }
  447 +
  448 + /**
  449 + * 利用正则表达式判断字符串是否是数字
  450 + *
  451 + * @param str
  452 + * @return
  453 + */
  454 + public static boolean isNumeric(String str) {
  455 + if (str == null || str.trim().length() == 0) return false;
  456 + Pattern pattern = Pattern.compile("[0-9]*");
  457 + Matcher isNum = pattern.matcher(str);
  458 + if (!isNum.matches()) {
  459 + return false;
  460 + }
  461 + return true;
  462 + }
  463 +
  464 +
  465 + // private static final char[] cnNumbers = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
  466 + private static final char[] cnNumbers = {'零', '一', '二', '三', '四', '五', '六', '七', '八', '九'};
  467 + // private static final char[] series = {' ', '拾', '百', '仟', '万', '拾', '百', '仟', '亿'};
  468 + private static final char[] series = {' ', '十', '百', '千', '万', '十', '百', '千', '亿'};
  469 +
  470 + /**
  471 + * 取得大写形式的字符串
  472 + */
  473 + public static String getCnString(Integer value) {
  474 + // 整数部分
  475 + String integerPart = "";
  476 + // 小数部分
  477 + String floatPart = "";
  478 +
  479 + String original = value.toString();
  480 +
  481 + if (original.contains(".")) {
  482 + // 如果包含小数点
  483 + int dotIndex = original.indexOf(".");
  484 + integerPart = original.substring(0, dotIndex);
  485 + floatPart = original.substring(dotIndex + 1);
  486 + } else {
  487 + // 不包含小数点
  488 + integerPart = original;
  489 + }
  490 + // 因为是累加所以用StringBuffer
  491 + StringBuffer sb = new StringBuffer();
  492 +
  493 + // 整数部分处理
  494 + for (int i = 0; i < integerPart.length(); i++) {
  495 + int number = Integer.parseInt(String.valueOf(integerPart.charAt(i)));
  496 +
  497 + sb.append(cnNumbers[number]);
  498 + sb.append(series[integerPart.length() - 1 - i]);
  499 + }
  500 + // 小数部分处理
  501 + if (floatPart.length() > 0) {
  502 + sb.append("点");
  503 + for (int i = 0; i < floatPart.length(); i++) {
  504 + int number = Integer.parseInt(String.valueOf(floatPart.charAt(i)));
  505 +
  506 + sb.append(cnNumbers[number]);
  507 + }
  508 + }
  509 +
  510 + // 返回拼接好的字符串
  511 + return sb.toString().trim();
  512 + }
  513 +
  514 +
  515 +}
lib_media/src/main/java/com/cnlive/media/ImagePicker.java
@@ -11,7 +11,6 @@ import com.cnlive.media.media.entity.Media; @@ -11,7 +11,6 @@ import com.cnlive.media.media.entity.Media;
11 import com.cnlive.media.ui.activity.MediaActivity; 11 import com.cnlive.media.ui.activity.MediaActivity;
12 import com.cnlive.media.ui.activity.MediaPreviewActivity; 12 import com.cnlive.media.ui.activity.MediaPreviewActivity;
13 import com.cnlive.media.ui.activity.RecordActivity; 13 import com.cnlive.media.ui.activity.RecordActivity;
14 -import com.qiniu.pili.droid.shortvideo.PLShortVideoEnv;  
15 14
16 import java.util.ArrayList; 15 import java.util.ArrayList;
17 16
lib_media/src/main/java/com/cnlive/media/frame/view/ImageCropView.java
@@ -6,8 +6,8 @@ import android.graphics.Bitmap; @@ -6,8 +6,8 @@ import android.graphics.Bitmap;
6 import android.net.Uri; 6 import android.net.Uri;
7 import android.os.Build; 7 import android.os.Build;
8 import android.text.TextUtils; 8 import android.text.TextUtils;
  9 +import android.widget.Toast;
9 10
10 -import com.cnlive.libs.base.util.AlertUtil;  
11 import com.cnlive.libs.base.util.FileUtils; 11 import com.cnlive.libs.base.util.FileUtils;
12 import com.cnlive.media.R; 12 import com.cnlive.media.R;
13 import com.cnlive.media.media.entity.Media; 13 import com.cnlive.media.media.entity.Media;
@@ -126,12 +126,12 @@ public class ImageCropView implements MvpView { @@ -126,12 +126,12 @@ public class ImageCropView implements MvpView {
126 126
127 public void showMessage(String message) { 127 public void showMessage(String message) {
128 if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; 128 if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return;
129 - AlertUtil.showDeftToast(mActivity, message); 129 + Toast.makeText(mActivity,message,Toast.LENGTH_SHORT).show();
130 } 130 }
131 131
132 public void showSucessMessage(String message) { 132 public void showSucessMessage(String message) {
133 if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return; 133 if (TextUtils.isEmpty(message) || mActivity.isFinishing()) return;
134 - AlertUtil.showSuccessToast(mActivity, message); 134 + Toast.makeText(mActivity,message,Toast.LENGTH_SHORT).show();
135 } 135 }
136 136
137 137
lib_media/src/main/res/values/dimens.xml
@@ -17,4 +17,6 @@ @@ -17,4 +17,6 @@
17 <dimen name="activity_vertical_margin">16dp</dimen> 17 <dimen name="activity_vertical_margin">16dp</dimen>
18 <dimen name="list_divider_height">1px</dimen> 18 <dimen name="list_divider_height">1px</dimen>
19 <dimen name="list_divider_height_negative">-1px</dimen> 19 <dimen name="list_divider_height_negative">-1px</dimen>
  20 + <item name="status_bar_util_fake_status_bar_view" type="id"/>
  21 + <item name="status_bar_util_translucent_view" type="id"/>
20 </resources> 22 </resources>
lib_media/src/main/res/values/styles.xml
1 <?xml version="1.0" encoding="utf-8"?> 1 <?xml version="1.0" encoding="utf-8"?>
2 <resources> 2 <resources>
3 - <style name="AppTheme" parent="QMUI.Compat.NoActionBar">  
4 - <!-- 配置Android提供的theme -->  
5 - <item name="android:listPreferredItemHeight">?attr/qmui_list_item_height_higher</item>  
6 - <item name="android:listPreferredItemHeightSmall">?attr/qmui_list_item_height</item>  
7 - <item name="colorPrimaryDark">@color/transparent</item>  
8 - <!-- 配置qmui提供的theme -->  
9 - <item name="qmui_config_color_blue">#FFFFFF</item>  
10 - <item name="qmui_content_spacing_horizontal">20dp</item>  
11 - <item name="qmui_content_padding_horizontal">@dimen/qmui_content_spacing_horizontal</item>  
12 - <item name="windowActionBar">false</item>  
13 - <item name="windowNoTitle">true</item>  
14 -  
15 - <!-- 配置app自己的theme -->  
16 - <!--<item name="app_primary_color">@color/qmui_config_color_white</item>-->  
17 - <!--<item name="app_content_bg_color">@color/qmui_config_color_white</item>-->  
18 -  
19 - <item name="qmui_bottom_sheet_grid_item_mini_width">96dp</item>  
20 - </style>  
21 -  
22 - <style name="BtnOkStyle">  
23 - <item name="android:layout_width">wrap_content</item>  
24 - <item name="android:layout_height">40dp</item>  
25 - <item name="android:enabled">false</item>  
26 - <item name="android:paddingLeft">@dimen/imagepicker_padding</item>  
27 - <item name="android:paddingRight">@dimen/imagepicker_padding</item>  
28 - <item name="android:text">@string/btn_imagepicker_ok</item>  
29 - <item name="android:textColor">@drawable/imagepicker_btn_ok_tv_selector</item>  
30 - <item name="android:background">@drawable/imagepicker_btn_ok_bg_selector</item>  
31 - </style>  
32 -  
33 - <!--图片文件夹pop动画-->  
34 - <style name="FloderPopAnimStyle">  
35 - <item name="android:windowEnterAnimation">@anim/imagepicker_pop_slide_in</item>  
36 - <item name="android:windowExitAnimation">@anim/imagepicker_pop_slide_out</item>  
37 - </style>  
38 3
39 4
40 <style name="FullActivityThemeStyle" parent="QMUI.NoActionBar" > 5 <style name="FullActivityThemeStyle" parent="QMUI.NoActionBar" >