(itemView) {
+ LinearLayout layout;
+ ImageView imageView;
+
+ @Override
+ protected void initView(View itemView) {
+ layout = itemView.findViewById(R.id.ll_img_parent);
+ imageView = getImageView();
+ if (imageView != null) {
+ layout.removeAllViews();
+ layout.addView(imageView);
+ } else {
+ imageView = itemView.findViewById(R.id.image);
+ }
+ }
+
+ @Override
+ public void updateUI(Banner data) {
+ if (circle) {
+ ImageUtils.loadImageCircleBead(imageView, data.getImageUrl(), 4);
+ } else {
+ ImageUtils.loadImage(imageView, data.getImageUrl());
+ }
+ }
+ };
+ }
+
+ @Override
+ public int getLayoutId() {
+ return R.layout.layout_banner_img;
+ }
+
+ /**
+ * 可以传入自定义的ImageView
+ *
+ * @return ImageView
+ */
+ public ImageView getImageView() {
+ return null;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java
new file mode 100644
index 0000000..3c5af2d
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/adapter/FragmentPagerAdapter.java
@@ -0,0 +1,94 @@
+package com.wss.common.adapter;
+
+import android.util.Log;
+
+import com.wss.common.base.BaseFragment;
+import com.wss.common.bean.HorizontalTabTitle;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentStatePagerAdapter;
+
+
+/**
+ * Describe:滑动Fragment适配器
+ * 如果滑动Fragment是同一个 使用双参构造方法 覆写 getTabFragment 返回Fragment
+ * 如果滑动Fragment是不同的Fragment 使用第三参构造方法 传入对应的Fragment集合
+ *
+ * Created by 吴天强 on 2018/10/22.
+ */
+public class FragmentPagerAdapter extends FragmentStatePagerAdapter {
+ private List titles;
+ private List fragments;
+
+ /**
+ * 使用该构造方法 必须重写 getTabFragment 返回对应的Fragment
+ *
+ * @param fm FragmentManager
+ * @param titles Tab
+ */
+ public FragmentPagerAdapter(FragmentManager fm, List titles) {
+ this(fm, titles, null);
+ }
+
+ /**
+ * @param fm FragmentManager
+ * @param titles Tab
+ * @param fragments 滑动的Fragment集合
+ */
+ public FragmentPagerAdapter(FragmentManager fm, List titles, List fragments) {
+ super(fm);
+ this.titles = titles;
+ this.fragments = fragments;
+ }
+
+
+ @Override
+ public int getCount() {
+ return titles != null ? titles.size() : 0;
+ }
+
+
+ @NotNull
+ @Override
+ public Fragment getItem(int position) {
+ Log.e("调用了Fragment", "postion:" + position);
+ BaseFragment fragment = null;
+ if (fragments == null || fragments.isEmpty()) {
+ fragment = getTabFragment();
+ } else {
+ fragment = fragments.get(position);
+ }
+ if (fragment == null) {
+ throw new NullPointerException("Switch Fragment can not be empty!");
+ }
+ fragment.setTabTitle(titles.get(position));
+ return fragment;
+ }
+
+ @Override
+ public int getItemPosition(@NonNull Object object) {
+ return POSITION_NONE;
+ }
+
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return titles.get(position).getTitle();
+ }
+
+ /**
+ * 使用两参构造方法 必须重写 该方法 返回对应的Fragment
+ *
+ * @return BaseFragment
+ */
+ public BaseFragment getTabFragment() {
+ return null;
+ }
+
+}
diff --git a/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java b/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java
deleted file mode 100644
index 1c291db..0000000
--- a/common_base/src/main/java/com/wss/common/base/ActionBarActivity.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.wss.common.base;
-
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-
-import com.wss.common.base.mvp.BasePresenter;
-import com.wss.common.widget.ActionBar;
-
-/**
- * Describe:所有带actionBar的Activity基类
- * Created by 吴天强 on 2018/10/18.
- */
-
-public abstract class ActionBarActivity extends BaseMvpActivity
{
-
- // @BindView(R2.id.actionbar)
- protected ActionBar actionBar;
-
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- actionBar = findViewById(R.id.actionbar);
- }
-
- protected void setTitleText(String title) {
- if (actionBar != null) {
- actionBar.setCenterText(title);
- }
- }
-
- protected void setTitleText(int title) {
- if (actionBar != null) {
- actionBar.setCenterText(getString(title));
- }
- }
-
- @Override
- protected boolean isActionBar() {
- return true;
- }
-}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java b/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java
new file mode 100644
index 0000000..5f2e01f
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/BaseActionBarActivity.java
@@ -0,0 +1,240 @@
+package com.wss.common.base;
+
+import android.os.Bundle;
+import android.view.View;
+
+import com.wss.common.base.mvp.BasePresenter;
+import com.wss.common.widget.ActionBar;
+
+import androidx.annotation.Nullable;
+import butterknife.BindView;
+
+/**
+ * Describe:所有带actionBar的Activity基类
+ * Created by 吴天强 on 2018/10/18.
+ */
+public abstract class BaseActionBarActivity
extends BaseMvpActivity
{
+
+ @BindView(R2.id.actionbar)
+ ActionBar actionBar;
+
+ @BindView(R2.id.action_bar_line)
+ View actionBarLine;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ actionBar.setVisibility(View.VISIBLE);
+ //沉浸式状态栏
+ setImmersionBarColor(R.color.white);
+ }
+
+
+ /**
+ * 设置左边文字
+ *
+ * @param text 文字
+ */
+ protected void setLeftText(String text) {
+ setLeftText(text, null);
+ }
+
+ /**
+ * @param text 文字
+ * @param listener 事件监听
+ */
+ protected void setLeftText(String text, View.OnClickListener listener) {
+ setLeftText(text, R.color.color_333333, listener);
+ }
+
+ /**
+ * 设置左边文字
+ *
+ * @param text 文字
+ * @param textColor 文字颜色
+ * @param listener 事件监听
+ */
+ protected void setLeftText(String text, int textColor, View.OnClickListener listener) {
+ if (actionBar != null) {
+ if (textColor != 0) {
+ actionBar.setLeftTextColor(getResources().getColor(textColor));
+ }
+ actionBar.setLeftText(text, listener);
+ }
+ }
+
+ /**
+ * 设置左边icon
+ *
+ * @param drawable icon resId
+ * @param listener 事件监听
+ */
+ protected void setLeftIcon(int drawable, View.OnClickListener listener) {
+ if (actionBar != null) {
+ actionBar.setLeftIcon(drawable, listener);
+ }
+ }
+
+ /**
+ * 设置左边icon
+ *
+ * @param listener 事件监听
+ */
+ protected void setLeftIcon(View.OnClickListener listener) {
+ setLeftIcon(R.drawable.ic_back_black, listener);
+ }
+
+ /**
+ * 设置左边View
+ *
+ * @param view view
+ */
+ protected void setLeftView(View view) {
+ if (actionBar != null) {
+ actionBar.setLeftView(view);
+ }
+ }
+
+ /**
+ * 设置中间文字
+ *
+ * @param text text
+ */
+ protected void setCenterText(int text) {
+ setCenterText(getString(text));
+ }
+
+ /**
+ * 设置中间文字
+ *
+ * @param text text
+ */
+ protected void setCenterText(String text) {
+ setCenterText(text, R.color.color_333333);
+ }
+
+ /**
+ * 设置中间文字
+ *
+ * @param text text
+ * @param textColor 文字颜色
+ */
+ protected void setCenterText(String text, int textColor) {
+ setCenterText(text, textColor, null);
+ }
+
+ /**
+ * 设置中间文字
+ *
+ * @param text text
+ * @param textColor 文字颜色
+ * @param listener 事件监听
+ */
+ protected void setCenterText(String text, int textColor, View.OnClickListener listener) {
+ if (actionBar != null) {
+ if (textColor != 0) {
+ actionBar.setCenterTextColor(textColor);
+ }
+ //加粗
+ actionBar.setCenterTextBold(true);
+ actionBar.setCenterText(text, listener);
+ }
+ }
+
+ /**
+ * 设置中间View
+ *
+ * @param view view
+ */
+ protected void setCenterView(View view) {
+ if (actionBar != null) {
+ actionBar.setCenterView(view);
+ }
+ }
+
+ /**
+ * 设置右边文字
+ *
+ * @param resId 文字
+ * @param listener 事件监听
+ */
+ protected void setRightText(int resId, View.OnClickListener listener) {
+ setRightText(getString(resId), listener);
+ }
+
+ /**
+ * 设置右边文字
+ *
+ * @param text 文字
+ * @param listener 事件监听
+ */
+ protected void setRightText(String text, View.OnClickListener listener) {
+ setRightText(text, R.color.color_333333, listener);
+ }
+
+ /**
+ * 设置右边文字
+ *
+ * @param text 文字
+ * @param textColor 文字颜色
+ * @param listener 事件监听
+ */
+ protected void setRightText(String text, int textColor, View.OnClickListener listener) {
+ if (actionBar != null) {
+ if (textColor != 0) {
+ actionBar.setRightTextColor(textColor);
+ }
+ actionBar.setRightText(text, listener);
+ }
+ }
+
+ /**
+ * 设置右边icon
+ *
+ * @param drawable 图片
+ * @param listener 事件监听
+ */
+ protected void setRightIcon(int drawable, View.OnClickListener listener) {
+ if (actionBar != null) {
+ actionBar.setRightIcon(drawable, listener);
+ }
+ }
+
+ /**
+ * 设置右边View
+ *
+ * @param view view
+ */
+ protected void setRightView(View view) {
+ if (actionBar != null) {
+ actionBar.setRightView(view);
+ }
+ }
+
+ /**
+ * 返回顶部TitleBar
+ *
+ * @return ActionBar
+ */
+ protected ActionBar getTitleBar() {
+ return actionBar;
+ }
+
+ /**
+ * 设置ActionBar下面的横线
+ *
+ * @param show 是否显示
+ */
+ protected void showActionBarLine(boolean show) {
+ actionBarLine.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * 设置左边返回图标是否显示
+ *
+ * @param show 是否显示
+ */
+ public void showBackImg(boolean show) {
+ actionBar.showBackImg(show);
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseActivity.java b/common_base/src/main/java/com/wss/common/base/BaseActivity.java
index bc54385..6a3a911 100644
--- a/common_base/src/main/java/com/wss/common/base/BaseActivity.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseActivity.java
@@ -1,29 +1,24 @@
package com.wss.common.base;
import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
import android.os.Bundle;
-import android.provider.Settings;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
+import android.view.WindowManager;
import android.widget.TextView;
-import com.gyf.barlibrary.ImmersionBar;
-import com.orhanobut.logger.Logger;
+import com.gyf.immersionbar.BarHide;
+import com.gyf.immersionbar.ImmersionBar;
+import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.wss.common.bean.Event;
import com.wss.common.utils.EventBusUtils;
-import com.wss.common.widget.dialog.LoadingDialog;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
-import java.util.Arrays;
-
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
import butterknife.ButterKnife;
import butterknife.Unbinder;
@@ -31,44 +26,72 @@
* Describe:所有Activity的基类
* Created by 吴天强 on 2018/10/15.
*/
-
public abstract class BaseActivity extends FragmentActivity {
-
private Unbinder unbinder;
private ViewStub emptyView;
- protected Context mContext;
- protected ImmersionBar mImmersionBar;
- protected LoadingDialog loadingDialog;
-
+ protected Context context;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (isActionBar()) {
+ //加入Activity管理器
+ BaseApplication.i().getActivityManage().addActivity(this);
+ context = this;
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+ if (!isFullScreenLayout()) {
setContentView(R.layout.activity_base);
((ViewGroup) findViewById(R.id.fl_content)).addView(getLayoutInflater().inflate(getLayoutId(), null));
- } else {
- setContentView(getLayoutId());
+ unbinder = ButterKnife.bind(this);
}
- unbinder = ButterKnife.bind(this);
- mContext = this;
- //初始化ButterKnife
- //沉浸式状态栏
- initImmersionBar(R.color.blue);
- //加入Activity管理器
- BaseApplication.getApplication().getActivityManage().addActivity(this);
- if (regEvent()) {
+ if (registerEventBus()) {
EventBusUtils.register(this);
}
- loadingDialog = new LoadingDialog(mContext);
+ }
+ /**
+ * 设置沉浸栏颜色
+ *
+ * @param statusBarColor 颜色
+ */
+ protected void setImmersionBarColor(int statusBarColor) {
+ setImmersionBarColor(statusBarColor, false);
}
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- initView();
+ /**
+ * 设置沉浸栏颜色
+ *
+ * @param statusBarColor 沉浸栏颜色
+ */
+ protected void setImmersionBarColor(int statusBarColor, boolean fitsSystemWindows) {
+ setImmersionBarColor(statusBarColor, R.color.black, fitsSystemWindows);
+ }
+
+
+ /**
+ * 设置沉浸栏颜色
+ *
+ * @param statusBarColor 沉浸栏颜色
+ * @param navigationBarColor 沉浸栏图标颜色
+ */
+ protected void setImmersionBarColor(int statusBarColor, int navigationBarColor, boolean fitsSystemWindows) {
+ ImmersionBar.with(this)
+ .statusBarColor(statusBarColor)
+ .navigationBarColor(navigationBarColor)
+ .fitsSystemWindows(fitsSystemWindows)
+ .autoDarkModeEnable(true)
+ .statusBarDarkFont(true)
+ .init();
+ }
+
+ /**
+ * 隐藏状态栏、导航栏
+ */
+ protected void setImmersionBarHide() {
+ ImmersionBar.with(this)
+ .fitsSystemWindows(false)
+ .hideBar(BarHide.FLAG_HIDE_BAR)
+ .init();
}
@Override
@@ -77,43 +100,78 @@ protected void onDestroy() {
if (unbinder != null) {
unbinder.unbind();
}
- if (regEvent()) {
+ if (registerEventBus()) {
EventBusUtils.unregister(this);
}
- //必须调用该方法,防止内存泄漏
- if (mImmersionBar != null) {
- mImmersionBar.destroy();
- }
//将Activity从管理器移除
- BaseApplication.getApplication().getActivityManage().removeActivity(this);
+ BaseApplication.i().getActivityManage().removeActivity(this);
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ initView();
}
- //***************************************空页面方法*************************************
+ //***************************************空页面方法 start*************************************
+
+ /**
+ * 数据为空页面
+ */
protected void showEmptyView() {
- showEmptyOrErrorView(getString(R.string.no_data), R.drawable.bg_no_data);
+ showEmptyView(getString(R.string.no_data));
+ }
+
+ /**
+ * 数据为空页面
+ *
+ * @param text 显示文案
+ */
+ protected void showEmptyView(String text) {
+ showEmptyOrErrorView(text, R.drawable.bg_no_data, false);
}
+ /**
+ * 请求数据报错页面
+ */
protected void showErrorView() {
- showEmptyOrErrorView(getString(R.string.error_data), R.drawable.bg_no_net);
+ showErrorView(getString(R.string.network_error_server_error));
+ }
+
+ /**
+ * 请求数据报错页面
+ *
+ * @param text 显示文案
+ */
+ protected void showErrorView(String text) {
+ showEmptyOrErrorView(text, R.drawable.bg_no_net , true);
}
- public void showEmptyOrErrorView(String text, int img) {
- emptyView = findViewById(R.id.vs_empty);
- if (emptyView != null) {
- emptyView.setVisibility(View.VISIBLE);
- findViewById(R.id.iv_empty).setBackgroundResource(img);
- ((TextView) findViewById(R.id.tv_empty)).setText(text);
- findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onEmptyViewClick();
- }
- });
+ /**
+ * 请求数据报错或者为空页面
+ *
+ * @param text 提示文案
+ * @param iconResId 显示的icon
+ */
+ public void showEmptyOrErrorView(String text, int iconResId, boolean showRefreshButton) {
+ if (emptyView == null) {
+ emptyView = findViewById(R.id.vs_empty);
+ }
+ emptyView.setVisibility(View.VISIBLE);
+ findViewById(R.id.iv_empty).setBackgroundResource(iconResId);
+ ((TextView) findViewById(R.id.tv_empty)).setText(text);
+ if (showRefreshButton) {
+ View refreshButton = findViewById(R.id.tv_try_again);
+ refreshButton.setVisibility(View.VISIBLE);
+ refreshButton.setOnClickListener(v -> onRefreshRetry());
}
}
+ /**
+ * 隐藏空页面
+ */
protected void hideEmptyView() {
if (emptyView != null) {
emptyView.setVisibility(View.GONE);
@@ -121,84 +179,64 @@ protected void hideEmptyView() {
}
/**
- * 空页面被点击
+ * 刷新重试
*/
- protected void onEmptyViewClick() {
-
+ protected void onRefreshRetry() {
}
- //***************************************空页面方法*********************************
-
+ //***************************************空页面方法 end*********************************
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- Logger.e("permissions:" + Arrays.toString(permissions) + " grantResults:" + Arrays.toString(grantResults));
-
- //如果有未授权权限则跳转设置页面
- if (!requestPermissionsResult(grantResults)) {
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
- intent.setData(Uri.parse("package:" + getPackageName()));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+ /**
+ * 停止刷新和加载更多
+ *
+ * @param layout 刷新layout
+ */
+ protected void stopRefresh(SmartRefreshLayout layout) {
+ if (layout == null) {
+ return;
}
-
-
+ layout.finishLoadMore();
+ layout.finishRefresh();
}
/**
- * 判断授权结果
+ * 是否布局伸入状态栏类型Activity
+ *
+ * @return boolean
*/
- private boolean requestPermissionsResult(int[] grantResults) {
- for (int code : grantResults) {
- if (code == -1) {
- return false;
- }
- }
- return true;
+ protected boolean isFullScreenLayout() {
+ return false;
}
/**
- * 沉浸栏颜色
+ * 需要接收事件 重写该方法 并返回true
+ *
+ * @return boolean
*/
- protected void initImmersionBar(int color) {
- if (mImmersionBar == null) {
- mImmersionBar = ImmersionBar.with(this);
- if (color != 0) {
- mImmersionBar.statusBarColor(color);
- }
- mImmersionBar.init();
- }
+ protected boolean registerEventBus() {
+ return false;
}
-
/**
* 子类接受事件 重写该方法
+ *
+ * @param event 事件
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBus(Event event) {
-
}
-
/**
- * 是否需要ActionBar
- * TODO 暂时用此方法 后续优化
+ * 返回页面layout
+ *
+ * @return layout
*/
- protected boolean isActionBar() {
- return false;
- }
+ protected abstract int getLayoutId();
/**
- * 需要接收事件 重写该方法 并返回true
+ * 初始化View
*/
- protected boolean regEvent() {
- return false;
- }
-
- protected abstract int getLayoutId();
-
protected abstract void initView();
}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseApplication.java b/common_base/src/main/java/com/wss/common/base/BaseApplication.java
index c6992a3..2e64d20 100644
--- a/common_base/src/main/java/com/wss/common/base/BaseApplication.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseApplication.java
@@ -2,7 +2,7 @@
import android.app.Application;
import android.content.Context;
-import android.support.multidex.MultiDex;
+import android.widget.Toast;
import com.alibaba.android.arouter.launcher.ARouter;
import com.orhanobut.logger.AndroidLogAdapter;
@@ -10,26 +10,67 @@
import com.orhanobut.logger.LogcatLogStrategy;
import com.orhanobut.logger.Logger;
import com.orhanobut.logger.PrettyFormatStrategy;
+import com.scwang.smartrefresh.layout.SmartRefreshLayout;
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
+import com.scwang.smartrefresh.layout.header.ClassicsHeader;
+import com.wss.common.bean.User;
+import com.wss.common.constants.Constants;
+import com.wss.common.constants.Dic;
import com.wss.common.manage.ActivityManage;
-import com.wss.common.manage.CrashHandlerManage;
+import com.wss.common.utils.CacheUtils;
+import com.wss.common.utils.ToastUtils;
+import com.wss.common.utils.ValidUtils;
+import com.wss.common.utils.toast.ToastInterceptor;
+import com.wss.common.utils.toast.style.ToastBlackStyle;
+
+import org.jetbrains.annotations.Contract;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.X509TrustManager;
+
+import androidx.multidex.MultiDex;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.plugins.RxJavaPlugins;
+import okhttp3.ConnectionSpec;
+import okhttp3.OkHttpClient;
+import rxhttp.HttpSender;
+import rxhttp.wrapper.ssl.SSLSocketFactoryImpl;
+import rxhttp.wrapper.ssl.X509TrustManagerImpl;
/**
* Describe:基础Application所有需要模块化开发的module都需要继承自BaseApplication
* Created by 吴天强 on 2018/10/12.
*/
public class BaseApplication extends Application {
-
- //全局唯一的context
+ /**
+ * 全局上下文
+ */
private static BaseApplication application;
-
- //Activity管理器
+ /**
+ * Activity管理器
+ */
private ActivityManage activityManage;
+ /**
+ * 保存所有网络请求
+ */
+ private Map netDisposable;
+
+ /**
+ * 登录用户
+ */
+ private User user;
+
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
application = this;
- //MultiDex分包方法 必须最先初始化
+ //MultiDex分包方法 初始化
MultiDex.install(this);
}
@@ -37,37 +78,98 @@ protected void attachBaseContext(Context base) {
public void onCreate() {
super.onCreate();
activityManage = new ActivityManage();
- initARouter();
+ //初始化日志框架
initLogger();
- initCrashManage();
+ //初始化ARouter
+ initARouter();
+ //初始化Toast
+ initToast();
+ //初始化网络框架
+ initRXHttp();
+ //刷新框架
+ initRefreshLayout();
}
/**
- * 初始化崩溃管理器
+ * 初始化刷新框架
*/
- private void initCrashManage() {
- if (!BuildConfig.DEBUG) {
- CrashHandlerManage.getInstance()
- .init(getApplicationContext());
- }
+ private void initRefreshLayout() {
+ //设置全局的Header构建器
+ SmartRefreshLayout.setDefaultRefreshHeaderCreator((context, layout) -> {
+ //指定为经典Footer,默认是 BezierRadarHeader
+ return new ClassicsHeader(context);
+ });
+ //设置全局的Footer构建器
+ SmartRefreshLayout.setDefaultRefreshFooterCreator((context, layout) -> {
+ //指定为经典Footer,默认是 BallPulseFooter
+ return new ClassicsFooter(context).setDrawableSize(20);
+ });
}
+ /**
+ * B
+ * 初始化Toast
+ */
+ private void initToast() {
+ ToastUtils.setToastInterceptor(new ToastInterceptor() {
+ @Override
+ public boolean intercept(Toast toast, CharSequence text) {
+ boolean intercept = super.intercept(toast, text);
+ if (intercept) {
+ Logger.e("空 Toast");
+ } else {
+ Logger.d(text.toString());
+ }
+ return intercept;
+ }
+ });
+ // 初始化吐司工具类
+ ToastUtils.init(this, new ToastBlackStyle(this));
+ }
+
+ /**
+ * 初始化网络请求
+ */
+ private void initRXHttp() {
+ X509TrustManager trustManager = new X509TrustManagerImpl();
+ SSLSocketFactory sslSocketFactory = new SSLSocketFactoryImpl(trustManager);
+ HttpSender.setDebug(BuildConfig.DEBUG);
+ HttpSender.init(new OkHttpClient.Builder()
+ .connectTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS)
+ .readTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS)
+ .writeTimeout(Constants.Net.TIME_OUT, TimeUnit.SECONDS)
+ .connectionSpecs(Arrays.asList(ConnectionSpec.COMPATIBLE_TLS, ConnectionSpec.CLEARTEXT))
+ //添加信任证书
+ .sslSocketFactory(sslSocketFactory, trustManager)
+ //忽略Host验证
+ .hostnameVerifier(((hostname, session) -> true))
+ .build());
+ RxJavaPlugins.setErrorHandler(throwable -> {
+ //Rx全局异常处理
+ });
+ }
/**
* 初始化日志打印框架
*/
private void initLogger() {
FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder()
- .showThreadInfo(false) //(可选)是否显示线程信息。 默认值为true
- .methodCount(2) //(可选)要显示的方法行数。 默认2
- .methodOffset(7) //(可选)设置调用堆栈的函数偏移值,0的话则从打印该Log的函数开始输出堆栈信息,默认是0
- .logStrategy(new LogcatLogStrategy()) //(可选)更改要打印的日志策略。 默认LogCat
- .tag("AMD") //(可选)每个日志的全局标记。 默认PRETTY_LOGGER
+ //(可选)是否显示线程信息。 默认值为true
+ .showThreadInfo(false)
+ //(可选)要显示的方法行数。 默认2
+ .methodCount(0)
+ //(可选)设置调用堆栈的函数偏移值,0的话则从打印该Log的函数开始输出堆栈信息,默认是0
+ .methodOffset(7)
+ //(可选)更改要打印的日志策略。 默认LogCat
+ .logStrategy(new LogcatLogStrategy())
+ //(可选)每个日志的全局标记。 默认PRETTY_LOGGER
+ .tag("APP_LOG")
.build();
+
Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) {
@Override
public boolean isLoggable(int priority, String tag) {
- //DEBUG模式下不打印LOG
+ //非DEBUG模式下不打印LOG
return BuildConfig.DEBUG;
}
});
@@ -78,10 +180,12 @@ public boolean isLoggable(int priority, String tag) {
*/
private void initARouter() {
if (BuildConfig.DEBUG) {
- ARouter.openLog(); // 打印日志
- ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
+ // 打印日志
+ ARouter.openLog();
+ // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
+ ARouter.openDebug();
}
- ARouter.init(application);// 尽可能早,推荐在Application中初始化
+ ARouter.init(application);
}
/**
@@ -98,7 +202,8 @@ public void onTerminate() {
*
* @return BaseApplication
*/
- public static BaseApplication getApplication() {
+ @Contract(pure = true)
+ public static BaseApplication i() {
return application;
}
@@ -113,7 +218,9 @@ public void exitApp() {
}
/**
- * 返回Activity管理器
+ * 获取Activity管理器
+ *
+ * @return ActivityManage
*/
public ActivityManage getActivityManage() {
if (activityManage == null) {
@@ -122,5 +229,90 @@ public ActivityManage getActivityManage() {
return activityManage;
}
+ /**
+ * 获取存放的请求对象
+ *
+ * @return Map
+ */
+ public Map getNetDisposables() {
+ if (netDisposable == null) {
+ return new HashMap<>(16);
+ }
+ return netDisposable;
+ }
+
+ /**
+ * 退出登录清除换群
+ */
+ public void loginOutClean() {
+
+ }
+
+ /**
+ * 添加请求对象
+ *
+ * @param requestId 请求ID
+ * @param disposable 对象
+ */
+ public void addNetDisposable(String requestId, Disposable disposable) {
+ if (netDisposable == null) {
+ netDisposable = new HashMap<>(16);
+ }
+ netDisposable.put(requestId, disposable);
+ }
+
+ /**
+ * 根据请求ID移除该对象
+ *
+ * @param requestId 请求ID
+ */
+ public void removeNetDisposable(String requestId) {
+ netDisposable.remove(requestId);
+ }
+
+ /**
+ * 保存用户信息
+ *
+ * @param user 登录用户
+ */
+ public void setUser(User user) {
+ CacheUtils.get(this).put(Dic.LOGIN_USER_INFO, user);
+ this.user = user;
+ }
+
+ /**
+ * 获取用户信息
+ *
+ * @return User
+ */
+ public User getUser() {
+ if (!ValidUtils.isValid(user) || !ValidUtils.isValid(user.getId())) {
+ //如果保存的user为空,则去本地缓存中取
+ user = (User) CacheUtils.get(this).getAsObject(Dic.LOGIN_USER_INFO);
+ }
+ if (!ValidUtils.isValid(user)) {
+ //防止异常情况下getUser对象为null问题
+ user = new User();
+ }
+ return user;
+ }
+ /**
+ * 是否登录
+ *
+ * @return boolean
+ */
+ public boolean isLogged() {
+ User user = getUser();
+ return ValidUtils.isValid(user) && ValidUtils.isValid(user.getId());
+ }
+
+
+ public String getDeviceId() {
+ return "";
+ }
+
+ public String getLoginToken() {
+ return "";
+ }
}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/base/BaseFragment.java b/common_base/src/main/java/com/wss/common/base/BaseFragment.java
index 7e962f9..e463b3a 100644
--- a/common_base/src/main/java/com/wss/common/base/BaseFragment.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseFragment.java
@@ -2,21 +2,24 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.TextView;
-import com.wss.common.widget.dialog.LoadingDialog;
+import com.scwang.smartrefresh.layout.SmartRefreshLayout;
+import com.wss.common.bean.Event;
+import com.wss.common.bean.HorizontalTabTitle;
+import com.wss.common.utils.ValidUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import butterknife.ButterKnife;
import butterknife.Unbinder;
@@ -24,35 +27,36 @@
* Describe:所有Fragment的基类
* Created by 吴天强 on 2018/10/17.
*/
-
public abstract class BaseFragment extends Fragment {
+ protected Context context;
private ViewStub emptyView;
private View rootView;
private Unbinder unBinder;
- protected Context mContext;
- protected LoadingDialog loadingDialog;
-
+ private HorizontalTabTitle tabTitle;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mContext = getActivity();
- loadingDialog = new LoadingDialog(mContext);
+ context = getActivity();
}
+
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- rootView = inflater.inflate(R.layout.fragment_base, container, false);
+ rootView = inflater.inflate(R.layout.layout_base, container, false);
((ViewGroup) rootView.findViewById(R.id.fl_content)).addView(getLayoutInflater().inflate(getLayoutId(), null));
unBinder = ButterKnife.bind(this, rootView);
- if (regEvent()) {
- EventBus.getDefault().register(this);
+ if (registerEventBus()) {
+ if (!EventBus.getDefault().isRegistered(this)) {
+ EventBus.getDefault().register(this);
+ }
}
return rootView;
}
+ @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initView();
@@ -65,38 +69,73 @@ public void onDestroy() {
if (unBinder != null) {
unBinder.unbind();
}
- if (regEvent()) {
+ if (registerEventBus()) {
EventBus.getDefault().unregister(this);
}
}
- //***************************************空页面方法*************************************
+ //***************************************空页面方法 start *************************************
+
+ /**
+ * 数据为空页面
+ */
protected void showEmptyView() {
- showEmptyOrErrorView(getString(R.string.no_data), R.drawable.bg_no_data);
+ showEmptyView(getString(R.string.no_data));
+ }
+
+ /**
+ * 数据为空页面
+ *
+ * @param text 显示文案
+ */
+ protected void showEmptyView(String text) {
+ showEmptyOrErrorView(text, R.drawable.bg_no_data, false);
}
+ /**
+ * 请求数据报错页面
+ */
protected void showErrorView() {
- showEmptyOrErrorView(getString(R.string.error_data), R.drawable.bg_no_net);
+ showErrorView(getString(R.string.network_error_server_error));
+ }
+
+ /**
+ * 请求数据报错页面
+ *
+ * @param text 显示文案
+ */
+ protected void showErrorView(String text) {
+ showEmptyOrErrorView(text, R.drawable.bg_no_net, true);
}
- public void showEmptyOrErrorView(String text, int img) {
- emptyView = rootView.findViewById(R.id.vs_empty);
- if (emptyView != null) {
- emptyView.setVisibility(View.VISIBLE);
- rootView.findViewById(R.id.iv_empty).setBackgroundResource(img);
- ((TextView) rootView.findViewById(R.id.tv_empty)).setText(text);
- rootView.findViewById(R.id.ll_empty).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- onEmptyViewClick();
- }
- });
+ /**
+ * 请求数据报错或者为空页面
+ *
+ * @param text 提示文案
+ * @param iconResId 显示的icon
+ */
+ public void showEmptyOrErrorView(String text, int iconResId, boolean showRefreshButton) {
+ if (emptyView == null) {
+ emptyView = rootView.findViewById(R.id.vs_empty);
+ }
+ emptyView.setVisibility(View.VISIBLE);
+ rootView.findViewById(R.id.iv_empty).setBackgroundResource(iconResId);
+ ((TextView) rootView.findViewById(R.id.tv_empty)).setText(text);
+ View refreshButton = rootView.findViewById(R.id.tv_try_again);
+ if (showRefreshButton) {
+ refreshButton.setVisibility(View.VISIBLE);
+ refreshButton.setOnClickListener(v -> onRefreshRetry());
+ } else {
+ refreshButton.setVisibility(View.GONE);
}
}
+ /**
+ * 隐藏空页面
+ */
protected void hideEmptyView() {
if (emptyView != null) {
emptyView.setVisibility(View.GONE);
@@ -104,39 +143,78 @@ protected void hideEmptyView() {
}
/**
- * 空页面被点击
+ * 刷新重试
*/
- protected void onEmptyViewClick() {
+ protected void onRefreshRetry() {
+ }
+
+ //***************************************空页面方法 end*********************************
+ /**
+ * 停止刷新和加载更多
+ *
+ * @param layout 刷新layout
+ */
+ protected void stopRefresh(SmartRefreshLayout layout) {
+ if (layout == null) {
+ return;
+ }
+ layout.finishLoadMore();
+ layout.finishRefresh();
}
- //***************************************空页面方法*********************************
+ /**
+ * 返回Fragment的根布局
+ *
+ * @return View
+ */
+ protected View getRootView() {
+ return rootView;
+ }
/**
- * 给Fragment设置数据
+ * 给Fragment设置TabTile数据
+ *
+ * @param data tabtitle
*/
- public void setFragmentData(Object data) {
+ public void setTabTitle(HorizontalTabTitle data) {
+ this.tabTitle = data;
+ }
+ /**
+ * 返回ViewPager+Fragment滑动 设置给子Fragment的Tab数据
+ *
+ * @return HorizontalTabTitle
+ */
+ public HorizontalTabTitle getTabTitle() {
+ return ValidUtils.isValid(tabTitle) ? tabTitle : new HorizontalTabTitle("");
}
/**
* 子类接受事件 重写该方法
*/
@Subscribe(threadMode = ThreadMode.MAIN)
- public void onEventBus(Object event) {
+ public void onEventBus(Event event) {
}
/**
* 需要接收事件 重新该方法 并返回true
*/
- protected boolean regEvent() {
+ protected boolean registerEventBus() {
return false;
}
-
+ /**
+ * 返回页面layout
+ *
+ * @return layout
+ */
protected abstract int getLayoutId();
+ /**
+ * 初始化View
+ */
protected abstract void initView();
}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java b/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java
new file mode 100644
index 0000000..b6df48f
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/BaseFullScreenActivity.java
@@ -0,0 +1,34 @@
+package com.wss.common.base;
+
+
+import com.gyf.immersionbar.ImmersionBar;
+import com.wss.common.base.mvp.BasePresenter;
+
+/**
+ * Describe:布局需要伸入状态栏下面的Activity继承该类,
+ * 并通过setContentView来设置layout,重新注册ButterKnife
+ * Created by 吴天强 on 2020/4/28.
+ */
+public abstract class BaseFullScreenActivity extends BaseMvpActivity
{
+
+ @Override
+ protected boolean isFullScreenLayout() {
+ return true;
+ }
+
+ @Override
+ protected int getLayoutId() {
+ //该方法仅仅是为了实现父类的抽象方法,无任何意义,忽略即可
+ return R.layout.layout_nothing;
+ }
+
+ @Override
+ protected void initView() {
+ //布局可伸入状态栏
+ ImmersionBar.with(this)
+ .statusBarColor(R.color.transparent)
+ .statusBarDarkFont(true)
+ .fullScreen(true)
+ .init();
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java b/common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java
similarity index 67%
rename from common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java
rename to common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java
index 958205e..a1ab86f 100644
--- a/common_base/src/main/java/com/wss/common/base/HorizontalTabActivity.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseHorizontalTabActivity.java
@@ -1,24 +1,22 @@
package com.wss.common.base;
-import android.support.annotation.CallSuper;
-import android.support.v4.view.ViewPager;
-import com.wss.common.base.adapter.FragmentPagerAdapter;
+import com.wss.common.adapter.FragmentPagerAdapter;
import com.wss.common.base.mvp.BasePresenter;
import com.wss.common.bean.HorizontalTabTitle;
import com.wss.common.widget.PagerSlidingTabStrip;
import java.util.List;
+import androidx.annotation.CallSuper;
+import androidx.viewpager.widget.ViewPager;
import butterknife.BindView;
/**
* Describe:带水平选项卡的Activity
* Created by 吴天强 on 2018/10/22.
*/
-
-public abstract class HorizontalTabActivity
extends ActionBarActivity
{
-
+public abstract class BaseHorizontalTabActivity
extends BaseActionBarActivity
{
@BindView(R2.id.pst_tab)
PagerSlidingTabStrip tabStrip;
@@ -38,15 +36,24 @@ protected void initView() {
viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager(), getTabTitles()) {
@Override
public BaseFragment getTabFragment() {
- return HorizontalTabActivity.this.getTabFragment();
+ return BaseHorizontalTabActivity.this.getTabFragment();
}
});
tabStrip.setViewPager(viewPager);
}
+ /**
+ * 选项卡List
+ *
+ * @return List
+ */
protected abstract List getTabTitles();
+ /**
+ * 滑动Fragment
+ *
+ * @return BaseFragment
+ */
protected abstract BaseFragment getTabFragment();
-
}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java
index c523d75..df294f2 100644
--- a/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseMvpActivity.java
@@ -2,25 +2,30 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
+import android.text.TextUtils;
import com.wss.common.base.mvp.BasePresenter;
import com.wss.common.base.mvp.IBaseView;
+import com.wss.common.widget.dialog.LoadingDialog;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LifecycleOwner;
/**
* Describe:所有需要Mvp开发的Activity的基类
* Created by 吴天强 on 2018/10/15.
*/
-
+@SuppressWarnings("unchecked")
public abstract class BaseMvpActivity extends BaseActivity implements IBaseView {
- protected P presenter;
+ private P presenter;
+ private LoadingDialog loadingDialog;
-
- @SuppressWarnings("unchecked")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ loadingDialog = new LoadingDialog(context);
+ loadingDialog.setCancelable(loadingCancelable());
//创建present
presenter = createPresenter();
if (presenter != null) {
@@ -28,22 +33,45 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
}
}
-
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.detachView();
+ presenter = null;
}
+ }
+ /**
+ * 返回Presenter
+ *
+ * @return P
+ */
+ protected P getPresenter() {
+ return presenter;
}
- //***************************************IBaseView方法实现*************************************
+
+ //***************************************IBaseView方法实现 start*************************************
+
@Override
public void showLoading() {
+ showLoading("");
+ }
+
+ /**
+ * 显示加载框
+ *
+ * @param msg 加载框文字
+ */
+ public void showLoading(String msg) {
if (loadingDialog != null && !loadingDialog.isShowing()) {
+ if (!TextUtils.isEmpty(msg)) {
+ loadingDialog.setTitleText(msg);
+ }
loadingDialog.show();
}
+ hideEmptyView();
}
@Override
@@ -53,21 +81,41 @@ public void dismissLoading() {
}
}
+ /**
+ * 加载框是否可以取消
+ *
+ * @return boolean
+ */
+ protected boolean loadingCancelable() {
+ return true;
+ }
+
+
@Override
public void onEmpty(Object tag) {
-
+ dismissLoading();
}
@Override
public void onError(Object tag, String errorMsg) {
+ dismissLoading();
+ }
+ @Override
+ public LifecycleOwner getLifecycleOwner() {
+ return this;
}
@Override
public Context getContext() {
- return mContext;
+ return context;
}
- //***************************************IBaseView方法实现*************************************
+ //********************************x*******IBaseView方法实现 end*************************************
+ /**
+ * 创建Presenter
+ *
+ * @return Presenter
+ */
protected abstract P createPresenter();
}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java b/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java
index c04ef53..dc4ec42 100644
--- a/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java
+++ b/common_base/src/main/java/com/wss/common/base/BaseMvpFragment.java
@@ -1,31 +1,35 @@
package com.wss.common.base;
+
import android.os.Bundle;
-import android.support.annotation.Nullable;
import com.wss.common.base.mvp.BasePresenter;
import com.wss.common.base.mvp.IBaseView;
+import com.wss.common.widget.dialog.LoadingDialog;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.LifecycleOwner;
/**
* Describe:所有需要Mvp开发的Fragment的基类
* Created by 吴天强 on 2018/10/17.
*/
-
+@SuppressWarnings("unchecked")
public abstract class BaseMvpFragment
extends BaseFragment implements IBaseView {
- protected P presenter;
-
+ private P presenter;
+ private LoadingDialog loadingDialog;
- @SuppressWarnings("unchecked")
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- if (presenter == null) {
- presenter = createPresenter();
+ loadingDialog = new LoadingDialog(context);
+ loadingDialog.setCancelable(loadingCancelable());
+ //创建present
+ presenter = createPresenter();
+ if (presenter != null) {
presenter.attachView(this);
}
-
}
@Override
@@ -34,16 +38,26 @@ public void onDestroy() {
if (presenter != null) {
presenter.detachView();
}
+ }
+ /**
+ * 返回presenter
+ *
+ * @return P
+ */
+ protected P getPresenter() {
+ return presenter;
}
+ //***************************************IBaseView方法实现 start *************************************
+
- //***************************************IBaseView方法实现*************************************
@Override
public void showLoading() {
if (loadingDialog != null && !loadingDialog.isShowing()) {
loadingDialog.show();
}
+ hideEmptyView();
}
@Override
@@ -53,16 +67,36 @@ public void dismissLoading() {
}
}
+ /**
+ * 加载框是否可以取消
+ *
+ * @return boolean
+ */
+ protected boolean loadingCancelable() {
+ return true;
+ }
+
@Override
public void onEmpty(Object tag) {
-
+ dismissLoading();
}
@Override
public void onError(Object tag, String errorMsg) {
+ dismissLoading();
+ }
+ @Override
+ public LifecycleOwner getLifecycleOwner() {
+ return this;
}
- //***************************************IBaseView方法实现*************************************
+ //***************************************IBaseView方法实现 end*************************************
+
+ /**
+ * 创建Presenter
+ *
+ * @return Presenter
+ */
protected abstract P createPresenter();
}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java b/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java
new file mode 100644
index 0000000..0769b17
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/BaseRefreshListActivity.java
@@ -0,0 +1,114 @@
+package com.wss.common.base;
+
+import com.scwang.smartrefresh.layout.SmartRefreshLayout;
+import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
+import com.wss.common.base.mvp.BasePresenter;
+
+import androidx.annotation.CallSuper;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+
+/**
+ * Describe:带下拉刷新 上拉加载更多的Activity
+ * 内部实现为刷新控件 SmartRefreshLayout + 列表控件 RecyclerView
+ * Created by 吴天强 on 2018/10/23.
+ */
+public abstract class BaseRefreshListActivity
extends BaseActionBarActivity
{
+
+ @BindView(R2.id.ptrl_list)
+ SmartRefreshLayout refreshLayout;
+
+ @BindView(R2.id.recycle_view)
+ RecyclerView recyclerView;
+
+ /**
+ * 适配器
+ */
+ private RecyclerView.Adapter adapter;
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.layout_refresh;
+ }
+
+ @CallSuper
+ @Override
+ protected void initView() {
+ adapter = createAdapter();
+ refreshLayout.setOnRefreshLoadMoreListener(createRefreshListener());
+ recyclerView.setLayoutManager(getLayoutManager());
+ recyclerView.setAdapter(adapter);
+
+ }
+
+ @CallSuper
+ @Override
+ public void dismissLoading() {
+ super.dismissLoading();
+ stopRefresh();
+ }
+
+
+ @CallSuper
+ @Override
+ public void showLoading() {
+ super.showLoading();
+ hideEmptyView();
+ }
+
+ /**
+ * 停止刷新
+ */
+ protected void stopRefresh() {
+ refreshLayout.finishRefresh();
+ refreshLayout.finishLoadMore();
+ }
+
+ /**
+ * 获取刷新控件
+ *
+ * @return PullToRefreshLayout
+ */
+ protected SmartRefreshLayout getRefreshLayout() {
+ return refreshLayout;
+ }
+
+ /**
+ * 获取加载数据列表控件
+ *
+ * @return RecyclerView
+ */
+ protected RecyclerView getRecyclerView() {
+ return recyclerView;
+ }
+
+ /**
+ * 返回适配器
+ *
+ * @return RecyclerView.Adapter
+ */
+ protected RecyclerView.Adapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * 创建 RecyclerView LayoutManager
+ *
+ * @return RecyclerView.LayoutManager
+ */
+ protected abstract RecyclerView.LayoutManager getLayoutManager();
+
+ /**
+ * 创建刷新监听器
+ *
+ * @return OnPullRefreshListener
+ */
+ protected abstract OnRefreshLoadMoreListener createRefreshListener();
+
+ /**
+ * 创建列表适配器
+ *
+ * @return RecyclerView.Adapter
+ */
+ protected abstract RecyclerView.Adapter createAdapter();
+}
diff --git a/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java b/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java
new file mode 100644
index 0000000..a7d45c0
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/BaseRefreshListFragment.java
@@ -0,0 +1,112 @@
+package com.wss.common.base;
+
+
+import com.scwang.smartrefresh.layout.SmartRefreshLayout;
+import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
+import com.wss.common.base.mvp.BasePresenter;
+
+import androidx.annotation.CallSuper;
+import androidx.recyclerview.widget.RecyclerView;
+import butterknife.BindView;
+
+/**
+ * Describe:带下拉刷新 上拉加载更多的Fragment
+ * 内部实现为刷新控件 SmartRefreshLayout + 列表控件 RecyclerView
+ * Created by 吴天强 on 2018/10/23.
+ */
+public abstract class BaseRefreshListFragment
extends BaseMvpFragment
{
+
+ @BindView(R2.id.ptrl_list)
+ SmartRefreshLayout refreshLayout;
+
+ @BindView(R2.id.recycle_view)
+ RecyclerView recyclerView;
+ /**
+ * 适配器
+ */
+ private RecyclerView.Adapter adapter;
+
+ @Override
+ protected int getLayoutId() {
+ return R.layout.layout_refresh;
+ }
+
+ @CallSuper
+ @Override
+ protected void initView() {
+ adapter = createAdapter();
+ refreshLayout.setOnRefreshLoadMoreListener(createRefreshListener());
+ recyclerView.setLayoutManager(getLayoutManager());
+ recyclerView.setAdapter(adapter);
+ }
+
+ @CallSuper
+ @Override
+ public void dismissLoading() {
+ super.dismissLoading();
+ stopRefresh();
+ }
+
+ @CallSuper
+ @Override
+ public void showLoading() {
+ super.showLoading();
+ hideEmptyView();
+ }
+
+ /**
+ * 停止刷新
+ */
+ protected void stopRefresh() {
+ refreshLayout.finishRefresh();
+ refreshLayout.finishLoadMore();
+ }
+
+ /**
+ * 获取刷新控件
+ *
+ * @return PullToRefreshLayout
+ */
+ protected SmartRefreshLayout getRefreshLayout() {
+ return refreshLayout;
+ }
+
+ /**
+ * 获取加载数据列表控件
+ *
+ * @return RecyclerView
+ */
+ protected RecyclerView getRecyclerView() {
+ return recyclerView;
+ }
+
+ /**
+ * 返回适配器
+ *
+ * @return RecyclerView.Adapter
+ */
+ protected RecyclerView.Adapter getAdapter() {
+ return adapter;
+ }
+
+ /**
+ * 创建 RecyclerView LayoutManager
+ *
+ * @return RecyclerView.LayoutManager
+ */
+ protected abstract RecyclerView.LayoutManager getLayoutManager();
+
+ /**
+ * 创建刷新监听器
+ *
+ * @return OnPullRefreshListener
+ */
+ protected abstract OnRefreshLoadMoreListener createRefreshListener();
+
+ /**
+ * 创建列表适配器
+ *
+ * @return RecyclerView.Adapter
+ */
+ protected abstract RecyclerView.Adapter createAdapter();
+}
diff --git a/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java b/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java
deleted file mode 100644
index 552ecc4..0000000
--- a/common_base/src/main/java/com/wss/common/base/RefreshListActivity.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.wss.common.base;
-
-import android.support.annotation.CallSuper;
-import android.support.v7.widget.RecyclerView;
-
-import com.wss.common.listener.OnListItemClickListener;
-import com.wss.common.base.mvp.BasePresenter;
-import com.wss.common.widget.pulltorefresh.OnPullRefreshListener;
-import com.wss.common.widget.pulltorefresh.PullToRefreshLayout;
-
-import butterknife.BindView;
-
-/**
- * Describe:带下拉刷新 上拉加载更多的Activity
- * 内部实现为刷新控件 PullToRefreshLayout + 列表控件 RecyclerView
- * Created by 吴天强 on 2018/10/23.
- */
-public abstract class RefreshListActivity
extends ActionBarActivity
implements OnPullRefreshListener, OnListItemClickListener {
-
- @BindView(R2.id.ptrl_list)
- PullToRefreshLayout refreshLayout;
-
- @BindView(R2.id.recycle_view)
- RecyclerView recyclerView;
-
- protected RecyclerView.Adapter adapter;
-
-
- @Override
- protected int getLayoutId() {
- return R.layout.layout_refresh;
- }
-
- @CallSuper
- @Override
- protected void initView() {
- refreshLayout.setOnPullRefreshListener(this);
- recyclerView.setLayoutManager(getLayoutManager());
- adapter = createAdapter();
- recyclerView.setAdapter(adapter);
- }
-
- @CallSuper
- @Override
- public void dismissLoading() {
- super.dismissLoading();
- stopRefresh();
- hideEmptyView();
- }
-
- /**
- * 停止刷新
- */
- protected void stopRefresh() {
- refreshLayout.finishRefresh();
- refreshLayout.finishLoadMore();
-
- }
-
- protected abstract RecyclerView.LayoutManager getLayoutManager();
-
- protected abstract RecyclerView.Adapter createAdapter();
-}
diff --git a/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java b/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java
deleted file mode 100644
index 75874d9..0000000
--- a/common_base/src/main/java/com/wss/common/base/RefreshListFragment.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.wss.common.base;
-
-import android.support.annotation.CallSuper;
-import android.support.v7.widget.RecyclerView;
-
-import com.wss.common.listener.OnListItemClickListener;
-import com.wss.common.base.mvp.BasePresenter;
-import com.wss.common.widget.pulltorefresh.OnPullRefreshListener;
-import com.wss.common.widget.pulltorefresh.PullToRefreshLayout;
-
-import butterknife.BindView;
-
-/**
- * Describe:带下拉刷新 上拉加载更多的Fragment
- * 内部实现为刷新控件 PullToRefreshLayout + 列表控件 RecyclerView
- * Created by 吴天强 on 2018/10/23.
- */
-public abstract class RefreshListFragment
extends BaseMvpFragment
implements OnPullRefreshListener, OnListItemClickListener {
-
-
- @BindView(R2.id.ptrl_list)
- PullToRefreshLayout refreshLayout;
-
- @BindView(R2.id.recycle_view)
- RecyclerView recyclerView;
-
- protected RecyclerView.Adapter adapter;
-
- @Override
- protected int getLayoutId() {
- return R.layout.layout_refresh;
- }
-
- @CallSuper
- @Override
- protected void initView() {
- adapter = createAdapter();
- refreshLayout.setOnPullRefreshListener(this);
- recyclerView.setLayoutManager(getLayoutManager());
- recyclerView.setAdapter(adapter);
- }
-
- @CallSuper
- @Override
- public void dismissLoading() {
- super.dismissLoading();
- stopRefresh();
- hideEmptyView();
- }
-
- /**
- * 停止刷新
- */
- protected void stopRefresh() {
- refreshLayout.finishRefresh();
- refreshLayout.finishLoadMore();
-
- }
-
- protected abstract RecyclerView.LayoutManager getLayoutManager();
-
- protected abstract RecyclerView.Adapter createAdapter();
-}
diff --git a/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java b/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java
index 53b2747..77cce29 100644
--- a/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java
+++ b/common_base/src/main/java/com/wss/common/base/adapter/BaseListAdapter.java
@@ -2,34 +2,70 @@
import android.content.Context;
-import com.wss.common.listener.OnListItemClickListener;
+import com.wss.common.base.adapter.listener.OnListItemClickListener;
+import org.byteam.superadapter.IMulItemViewType;
import org.byteam.superadapter.SuperAdapter;
+import org.byteam.superadapter.SuperViewHolder;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Describe:万能适配器基类 适用于RecycleView ListView GridView等
- * 注意点:Item的最外层高度不能设置为 match_parent 否则滑动会出现混乱 目前还不知道原因、
+ * 注意点:Item的最外层高度不能设置为 match_parent 否则滑动会出现混乱[TODO]
* Created by 吴天强 on 2018/10/30.
*/
-
public abstract class BaseListAdapter extends SuperAdapter {
/**
* Item点击监听
*/
- protected OnListItemClickListener listener;
+ private OnListItemClickListener listener;
- public BaseListAdapter(Context context, List items, int layoutResId, OnListItemClickListener listener) {
- super(context, items, layoutResId);
+ /**
+ * 常规列表重写该方法
+ *
+ * @param context context
+ * @param mData 数据源
+ * @param layoutResId 布局文件
+ * @param listener Item点击回调
+ */
+ public BaseListAdapter(Context context, List mData, int layoutResId, OnListItemClickListener listener) {
+ super(context, mData, layoutResId);
this.listener = listener;
}
/**
- * 添加点击事件监听
+ * 多布局列表重写该方法
+ *
+ * @param context context
+ * @param mData 数据源
+ * @param multiItemViewType 多布局类型
*/
- public void setOnListItemClickListener(OnListItemClickListener listener) {
+ public BaseListAdapter(Context context, List mData, IMulItemViewType multiItemViewType) {
+ super(context, mData, multiItemViewType);
+ }
+
+ /**
+ * Item点击事件
+ *
+ * @param listener listener
+ */
+ public void setOnListItemClickListener(OnListItemClickListener listener) {
this.listener = listener;
}
+
+ @Override
+ public void onBind(@NotNull final SuperViewHolder viewHolder, int viewType, final int layoutPosition, T data) {
+ viewHolder.itemView.setOnClickListener(v -> {
+ if (listener != null) {
+ listener.onItemClick(data, layoutPosition);
+ }
+ });
+ onBindData(viewHolder, viewType, layoutPosition, data);
+ }
+
+ public abstract void onBindData(@NotNull SuperViewHolder holder, int viewType, int layoutPosition, @NotNull T data);
+
}
diff --git a/common_base/src/main/java/com/wss/common/base/adapter/FragmentPagerAdapter.java b/common_base/src/main/java/com/wss/common/base/adapter/FragmentPagerAdapter.java
deleted file mode 100644
index e099116..0000000
--- a/common_base/src/main/java/com/wss/common/base/adapter/FragmentPagerAdapter.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.wss.common.base.adapter;
-
-import android.support.annotation.NonNull;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
-import android.view.ViewGroup;
-
-import com.wss.common.base.BaseFragment;
-import com.wss.common.bean.HorizontalTabTitle;
-
-import java.util.List;
-
-/**
- * Describe:FragmentPagerAdapter
- * Created by 吴天强 on 2018/10/22.
- */
-
-public abstract class FragmentPagerAdapter extends FragmentStatePagerAdapter {
- private BaseFragment[] fragments;
- private List titles;
-
- public FragmentPagerAdapter(FragmentManager fm, List titles) {
- super(fm);
- this.titles = titles;
- }
-
- @Override
- public int getCount() {
- return titles != null ? titles.size() : 0;
- }
-
-
- @Override
- public Fragment getItem(int position) {
- if (fragments == null) {
- fragments = new BaseFragment[titles.size()];
- }
- BaseFragment fragment = getTabFragment();
- fragment.setFragmentData(titles.get(position));
- fragments[position] = fragment;
- return fragment;
- }
-
- @Override
- public int getItemPosition(@NonNull Object object) {
- return POSITION_NONE;
- }
-
- @Override
- public void startUpdate(ViewGroup container) {
- super.startUpdate(container);
- }
-
- @Override
- public CharSequence getPageTitle(int position) {
- return titles.get(position).getTitle();
- }
-
- public abstract BaseFragment getTabFragment();
-}
diff --git a/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java b/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java
new file mode 100644
index 0000000..6e5aa16
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/adapter/listener/OnListItemClickListener.java
@@ -0,0 +1,16 @@
+package com.wss.common.base.adapter.listener;
+
+/**
+ * Describe:RecycleView 点击事件监听
+ * Created by 吴天强 on 2018/10/18.
+ */
+public interface OnListItemClickListener {
+
+ /**
+ * Item点击事件
+ *
+ * @param data Data
+ * @param position position
+ */
+ void onItemClick(T data, int position);
+}
diff --git a/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java b/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java
index 5336724..2a1f161 100644
--- a/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java
+++ b/common_base/src/main/java/com/wss/common/base/bean/BaseBean.java
@@ -2,10 +2,11 @@
import java.io.Serializable;
+
/**
* Describe:Bean基类
* Created by 吴天强 on 2018/10/17.
*/
-
public class BaseBean implements Serializable {
+
}
diff --git a/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java b/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java
new file mode 100644
index 0000000..3ca9b7e
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/base/mvp/BaseModel.java
@@ -0,0 +1,27 @@
+package com.wss.common.base.mvp;
+
+
+import androidx.lifecycle.LifecycleOwner;
+
+/**
+ * Describe:网络请求基类
+ * Created by 吴天强 on 2019/7/11.
+ */
+public class BaseModel {
+
+ private LifecycleOwner lifecycleOwner;
+
+ public BaseModel(LifecycleOwner lifecycleOwner) {
+ this.lifecycleOwner = lifecycleOwner;
+ }
+
+ /**
+ * 返回生命周期所有者
+ *
+ * @return LifecycleOwner
+ */
+ protected LifecycleOwner getLifecycleOwner() {
+ return lifecycleOwner;
+ }
+
+}
diff --git a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java
index 06f79fa..ed3fccc 100644
--- a/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java
+++ b/common_base/src/main/java/com/wss/common/base/mvp/BasePresenter.java
@@ -2,24 +2,37 @@
import android.content.Context;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import androidx.lifecycle.LifecycleOwner;
+
/**
* Describe:Presenter基类
* Created by 吴天强 on 2018/10/17.
*/
+@SuppressWarnings("unchecked")
+public abstract class BasePresenter {
-public abstract class BasePresenter {
-
- private V view;
- private M module;
-
+ private V mProxyView;
+ private M model;
+ private WeakReference weakReference;
/**
* 绑定View
+ *
+ * @param view view
*/
public void attachView(V view) {
- this.view = view;
- if (this.module == null) {
- this.module = createModule();
+ weakReference = new WeakReference<>(view);
+ mProxyView = (V) Proxy.newProxyInstance(
+ view.getClass().getClassLoader(),
+ view.getClass().getInterfaces(),
+ new MvpViewHandler(weakReference.get()));
+ if (this.model == null) {
+ this.model = createModule();
}
}
@@ -27,40 +40,99 @@ public void attachView(V view) {
* 解绑View
*/
public void detachView() {
- this.view = null;
- this.module = null;
+ this.model = null;
+ if (!isViewDetached()) {
+ weakReference.clear();
+ weakReference = null;
+ }
}
/**
- * 是否与View建立连接
+ * 是否与View断开连接
*/
- protected boolean isViewAttached() {
- return view != null;
+ protected boolean isViewDetached() {
+ return weakReference == null || weakReference.get() == null;
}
+ /**
+ * 返回View
+ *
+ * @return view
+ */
protected V getView() {
- return view;
+ return mProxyView;
}
- protected M getModule() {
- return module;
+ /**
+ * 返回Model
+ *
+ * @return model
+ */
+ protected M getModel() {
+ return model;
}
+ /**
+ * 返回Context
+ *
+ * @return context
+ */
protected Context getContext() {
return getView().getContext();
}
+ /**
+ * 返回持有View的生命周期所有者
+ *
+ * @return LifecycleOwner
+ */
+ protected LifecycleOwner getLifecycleOwner() {
+ return getView().getLifecycleOwner();
+ }
+
+ /**
+ * 显示加载框
+ */
protected void showLoading() {
- view.showLoading();
+ getView().showLoading();
}
+ /**
+ * 隐藏加载框
+ */
protected void dismissLoading() {
- view.dismissLoading();
+ getView().dismissLoading();
}
-
/**
* 通过该方法创建Module
*/
protected abstract M createModule();
-}
+
+ /**
+ * 初始化方法
+ */
+ public abstract void start();
+
+
+ /**
+ * View代理类 防止 页面关闭P异步操作调用V 方法 空指针问题
+ */
+ private class MvpViewHandler implements InvocationHandler {
+
+ private IBaseView mvpView;
+
+ MvpViewHandler(IBaseView mvpView) {
+ this.mvpView = mvpView;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ //如果V层没被销毁, 执行V层的方法.
+ if (!isViewDetached()) {
+ return method.invoke(mvpView, args);
+ } //P层不需要关注V层的返回值
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/base/mvp/IBaseModule.java b/common_base/src/main/java/com/wss/common/base/mvp/IBaseModule.java
deleted file mode 100644
index e2a85b2..0000000
--- a/common_base/src/main/java/com/wss/common/base/mvp/IBaseModule.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.wss.common.base.mvp;
-
-/**
- * Describe:所有Module的基类
- * Created by 吴天强 on 2018/10/17.
- */
-
-public interface IBaseModule {
-
-}
diff --git a/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java b/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java
index 6672132..5b6f526 100644
--- a/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java
+++ b/common_base/src/main/java/com/wss/common/base/mvp/IBaseView.java
@@ -2,20 +2,51 @@
import android.content.Context;
+import androidx.lifecycle.LifecycleOwner;
+
/**
* Describe:所有View基类
* Created by 吴天强 on 2018/10/17.
*/
-
public interface IBaseView {
+ /**
+ * 显示加载框
+ */
void showLoading();
+ /**
+ * 隐藏加载框
+ */
void dismissLoading();
+ /**
+ * 空数据
+ *
+ * @param tag TAG
+ */
void onEmpty(Object tag);
+ /**
+ * 错误数据
+ *
+ * @param tag TAG
+ * @param errorMsg 错误信息
+ */
void onError(Object tag, String errorMsg);
+ /**
+ * 上下文
+ *
+ * @return context
+ */
Context getContext();
+
+ /**
+ * 返回页面生命周期
+ *
+ * @return LifecycleOwner
+ */
+ LifecycleOwner getLifecycleOwner();
+
}
diff --git a/common_base/src/main/java/com/wss/common/bean/Banner.java b/common_base/src/main/java/com/wss/common/bean/Banner.java
new file mode 100644
index 0000000..265a5a0
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/bean/Banner.java
@@ -0,0 +1,35 @@
+package com.wss.common.bean;
+
+
+import com.wss.common.base.bean.BaseBean;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * description: 房源首页Banner实体
+ *
+ * @author 杨伟-tony
+ * create by 2020/5/21 20:40
+ */
+@Getter
+@Setter
+public class Banner extends BaseBean {
+ /**
+ * 图片链接
+ */
+ private String imageUrl;
+ /**
+ * 跳转链接
+ */
+ private String redirectUrl;
+
+ public Banner(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public Banner(String imageUrl, String redirectUrl) {
+ this.imageUrl = imageUrl;
+ this.redirectUrl = redirectUrl;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/bean/Event.java b/common_base/src/main/java/com/wss/common/bean/Event.java
index c5d1b36..554e1cb 100644
--- a/common_base/src/main/java/com/wss/common/bean/Event.java
+++ b/common_base/src/main/java/com/wss/common/bean/Event.java
@@ -1,5 +1,8 @@
package com.wss.common.bean;
+
+import com.wss.common.base.bean.BaseBean;
+
import lombok.Getter;
import lombok.Setter;
@@ -7,15 +10,19 @@
* Describe:EventBus事件类
* Created by 吴天强 on 2018/10/22.
*/
-
@Getter
@Setter
-public class Event {
+public class Event extends BaseBean {
+ /**
+ * 事件
+ */
private String action;
+ /**
+ * 事件附带数据
+ */
private T data;
-
public Event(String action) {
this.action = action;
}
@@ -25,5 +32,4 @@ public Event(String action, T data) {
this.data = data;
}
-
}
diff --git a/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java b/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java
index e6215a6..2892986 100644
--- a/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java
+++ b/common_base/src/main/java/com/wss/common/bean/HorizontalTabTitle.java
@@ -1,18 +1,25 @@
package com.wss.common.bean;
+
import com.wss.common.base.bean.BaseBean;
import lombok.Getter;
import lombok.Setter;
/**
- * Describe:水平选项卡Title
+ * Describe:水平选项卡标题
* Created by 吴天强 on 2018/10/22.
*/
@Getter
@Setter
public class HorizontalTabTitle extends BaseBean {
+ /**
+ * 显示标题文字
+ */
private String title;
+ /**
+ * 标题其他附带数据
+ */
private T data;
public HorizontalTabTitle(String title) {
@@ -22,5 +29,7 @@ public HorizontalTabTitle(String title) {
public HorizontalTabTitle(String title, T data) {
this.title = title;
this.data = data;
+
}
+
}
diff --git a/common_base/src/main/java/com/wss/common/bean/SelectorData.java b/common_base/src/main/java/com/wss/common/bean/SelectorData.java
new file mode 100644
index 0000000..85ec54c
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/bean/SelectorData.java
@@ -0,0 +1,29 @@
+package com.wss.common.bean;
+
+import com.contrarywind.interfaces.IPickerViewData;
+import com.wss.common.base.bean.BaseBean;
+import com.wss.common.utils.ValidUtils;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describe:弹窗选择器数据Bean
+ * Created by 吴天强 on 2020/4/21.
+ */
+@Getter
+@Setter
+public class SelectorData extends BaseBean implements IPickerViewData {
+ private String name;
+ private T data;
+
+ public SelectorData(String name, T data) {
+ this.name = name;
+ this.data = data;
+ }
+
+ @Override
+ public String getPickerViewText() {
+ return ValidUtils.isValid(name) ? name : "";
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/bean/Template.java b/common_base/src/main/java/com/wss/common/bean/Template.java
new file mode 100644
index 0000000..ecfaff6
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/bean/Template.java
@@ -0,0 +1,55 @@
+package com.wss.common.bean;
+
+import com.wss.common.base.bean.BaseBean;
+import com.wss.common.constants.Constants;
+
+import java.util.Map;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describe:可跳转的模板
+ * Created by 吴天强 on 2018/11/13.
+ */
+@Getter
+@Setter
+public class Template extends BaseBean {
+
+ private String title;
+ private int res;
+ private String describe;
+ private Class clazz;
+ /**
+ * 模块外跳转链接
+ */
+ private String url;
+ /**
+ * 页面跳转类型
+ */
+ private int type;
+ /**
+ * 其他附加参数
+ */
+ private Map params;
+
+ public Template(String title, String url, int type, String describe) {
+ this.title = title;
+ this.url = url;
+ this.type = type;
+ this.describe = describe;
+ }
+
+ public Template(String title, Class clazz, String describe) {
+ this.title = title;
+ this.clazz = clazz;
+ this.type = Constants.TemplateType.ACTIVITY;
+ this.describe = describe;
+ }
+
+ public Template(String title, int res, Class clazz) {
+ this.title = title;
+ this.res = res;
+ this.clazz = clazz;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/bean/User.java b/common_base/src/main/java/com/wss/common/bean/User.java
new file mode 100644
index 0000000..7f058ba
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/bean/User.java
@@ -0,0 +1,42 @@
+package com.wss.common.bean;
+
+import com.wss.common.base.bean.BaseBean;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describe:置业顾问信息
+ * Created by 吴天强 on 2020/5/6.
+ */
+@Getter
+@Setter
+public class User extends BaseBean {
+
+ /**
+ * email : banshengcy@163.com
+ * icon :
+ * id : 1260
+ * password : *******
+ * token :
+ * type : 0
+ * username : 于慢慢家的吴蜀黍
+ */
+
+ private Integer id;
+ private String username;
+ private String email;
+ private String icon;
+ private String password;
+ private String token;
+ private int type;
+
+ public User() {
+ }
+
+ public User(String username, String password) {
+ this.username = username;
+ this.password = password;
+ }
+
+}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java b/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java
index 969f851..11e1eb7 100644
--- a/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java
+++ b/common_base/src/main/java/com/wss/common/constants/ARouterConfig.java
@@ -4,21 +4,41 @@
* Describe:路由页面常量配置 注意:路径至少需要两级 {/xx/xx}
* Created by 吴天强 on 2018/10/16.
*/
-
public interface ARouterConfig {
- //************************************Main模块*****************************************
+ //************************************Main模块*****************************************/
+ /**
+ * 订单列表
+ */
+ String MAIN_ORDER_LIST = "/main/OrderListActivity";
//*************************************玩安卓模块*****************************************/
/**
* 玩安卓首页
*/
- String WAN_MAIN_ACTIVITY = "/wan/WanMainActivity";
+ String WAN_MAIN_FRAGMENT = "/wan/HomeFragment";
+ /**
+ * 我的收藏
+ */
+ String WAN_COLLECTION = "/wan/CollectionActivity";
- //*************************************商城模块*****************************************/
+ //*************************************商城模块******************************************/
/**
* 商场首页
*/
String MARKET_MAIN_ACTIVITY = "/market/MarketMainActivity";
+
+
+ //*************************************User模块*****************************************/
+ /**
+ * 用户模块
+ */
+ String USER_MAIN_FRAGMENT = "/user/UserFragment";
+ /**
+ * 登录
+ */
+ String USER_LOGIN = "/user/LoginActivity";
+
+
}
diff --git a/common_base/src/main/java/com/wss/common/constants/Constant.java b/common_base/src/main/java/com/wss/common/constants/Constant.java
deleted file mode 100644
index deca4c9..0000000
--- a/common_base/src/main/java/com/wss/common/constants/Constant.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.wss.common.constants;
-
-/**
- * Describe:常量存放
- * Created by 吴天强 on 2017/10/9.
- */
-
-public class Constant {
-
- /**
- * 服务器类型
- * SERVER_DEVELOP 开发环境
- * SERVER_TEST 测试环境
- * SERVER_PRODUCTION 生产环境
- */
- public static final int SERVER_TYPE = ServerType.SERVER_DEVELOP;
-
- /**
- * 服务器类型
- */
- public class ServerType {
- public static final int SERVER_DEVELOP = 0;//开发环境
- public static final int SERVER_TEST = 1;//测试环境
- public static final int SERVER_PRODUCTION = 2;//生产环境
- }
-
-
- /**
- * 模块类型
- */
- public static final int MODULE_TYPE_SHUTTLE = 0;
- public static final int MODULE_TYPE_CHART = 1;
- public static final int MODULE_TYPE_DEALS = 2;
-
-
- /**
- * 默认日期格式
- */
- public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd";
- public static final String DATE_FORMAT_LINE = "yyyy-MM-dd";
- public static final String DATE_FORMAT_DEFAULT = DATE_FORMAT_SLASH + " HH:mm:ss";
-
- public static final String ERROR_MESSAGE = "网络连接失败";
-
-
-}
diff --git a/common_base/src/main/java/com/wss/common/constants/Constants.java b/common_base/src/main/java/com/wss/common/constants/Constants.java
new file mode 100644
index 0000000..10883d1
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/constants/Constants.java
@@ -0,0 +1,159 @@
+package com.wss.common.constants;
+
+import android.content.Context;
+
+import com.wss.common.base.BaseApplication;
+
+/**
+ * Describe:常量存放
+ * Created by 吴天强 on 2017/10/9.
+ */
+public interface Constants {
+ /**
+ * 无法分类的散装常量
+ */
+ interface Common {
+ /**
+ * android
+ */
+ int PLATFORM_ANDROID = 1;
+
+ /**
+ * 渠道名称
+ */
+ String CHANEL = "android";
+ /**
+ * API 版本
+ */
+ String API_VERSION = "1.0";
+ }
+
+
+ /**
+ * WebView相关配置
+ */
+ interface WebView {
+ String CACHE_DIR = BaseApplication.i().getDir("cache", Context.MODE_PRIVATE).getPath();
+ }
+
+
+ /**
+ * 网络请求相关
+ */
+ interface Net {
+ //response
+ String STATE = "errorCode";
+ String MESSAGE = "errorMsg";
+ String DATA = "data";
+
+ //request
+ String HEADER_CHANNEL = "channel";
+ String HEADER_API_VERSION = "apiVersion";
+ String HEADER_DEVICE_ID = "deviceid";
+ String HEADER_TOKEN = "token";
+ String HEADER_APP_VERSION = "appVersion";
+ String HEADER_IP = "ip";
+ String REQUEST_ID = "requestId";
+ String REQUEST_DATA = "requestData";
+ /**
+ * 超时时间 单位:秒
+ */
+ int TIME_OUT = 30;
+
+ /**
+ * 接口响应码
+ */
+ interface Status {
+ /**
+ * 处理成功
+ */
+ String CODE_SUCCESS = "0";
+ /**
+ * 该用户已经被禁用
+ */
+ String CODE_ACCOUNT_DISABLE = "1111";
+ /**
+ * 该用户已经离职
+ */
+ String CODE_ACCOUNT_QUIT = "1112";
+ /**
+ * 账号被锁定
+ */
+ String CODE_ACCOUNT_LOCKED = "1113";
+ /**
+ * 此账户没有操作权限
+ */
+ String CODE_ACCOUNT_NO_AUTHORITY = "1114";
+ /**
+ * 此账户没有归属团队
+ */
+ String CODE_ACCOUNT_NO_TEAM = "1118";
+ /**
+ * 此账户同一项目归属多个团队
+ */
+ String CODE_ACCOUNT_MULTIPLE_TEAM = "1119";
+ /**
+ * Token过期
+ */
+ String CODE_TOKEN_EXPIRED = "1120";
+ /**
+ * 该用户的岗位信息有误
+ */
+ String CODE_ACCOUNT_POSITION_ERROR = "1128";
+
+ /**
+ * 参数异常
+ */
+ String INVALID_PARAMETER_ERROR = "403";
+ }
+ }
+
+ /**
+ * 选择文件的文件类型
+ */
+ interface FileType {
+ /**
+ * 图片
+ */
+ int IMAGE = 0;
+ /**
+ * 视频
+ */
+ int VIDEO = 1;
+ /**
+ * 音频
+ */
+ int AUDIO = 2;
+ /**
+ * 文档
+ */
+ int DOC = 3;
+ /**
+ * 压缩包
+ */
+ int PACKAGE = 4;
+ /**
+ * 其他
+ */
+ int OTHER = 5;
+ }
+
+ /**
+ * 数据库配置
+ */
+ interface DBConfig {
+ String DB_NAME = "AMD.db";
+ }
+
+ /**
+ * 页面跳转类型
+ */
+ interface TemplateType {
+
+ int ACTIVITY = 0;
+ int AROUTER = 1;
+ int WEB_VIEW = 2;
+ int SYS_BROWSER = 3;
+
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/constants/Dic.java b/common_base/src/main/java/com/wss/common/constants/Dic.java
new file mode 100644
index 0000000..9259e1f
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/constants/Dic.java
@@ -0,0 +1,84 @@
+package com.wss.common.constants;
+
+/**
+ * Describe:字典 存放Activity跳转传参key、缓存数据到SP中key等。
+ * Created by 吴天强 on 2018/11/13.
+ */
+public interface Dic {
+
+ /**
+ * 跳转画廊参数-图片集合
+ */
+ String IMAGE_LIST = "image_list";
+ /**
+ * 跳转画廊参数-图片起始位置
+ */
+ String IMAGE_POSITION = "image_position";
+ /**
+ * 跳转画廊参数-是否本地图片
+ */
+ String IMAGE_LOCAL = "image_local";
+ /**
+ * 跳转画廊参数-是否全屏显示
+ */
+ String FULL_SCREEN = "full_screen";
+
+ /**
+ * 通过路由跳转的Fragment的路径
+ */
+ String TARGET_FRAGMENT_PATH = "target_fragment_path";
+
+ /**
+ * 进入类型
+ */
+ String FROM_TYPE = "from_type";
+
+ /**
+ * 链接
+ */
+ String URL = "url";
+
+ /**
+ * 需要actionBar
+ */
+ String IS_ACTION_BAR = "is_action_bar";
+ /**
+ * actionBar 文字
+ */
+ String TITLE_TEXT = "title_text";
+ /**
+ * bundle带入的数据
+ */
+ String BUNDLE_DATA = "bundle_data";
+
+ /**
+ * 可选文件的最大值
+ */
+ String MAX_SELECT_FILE = "max_select_file";
+ /**
+ * 选择的文件路径列表
+ */
+ String SELECT_FILE_PATHS = "select_file_paths";
+ /**
+ * 商品信息
+ */
+ String GOODS_INFO = "goods_info";
+ /**
+ * 登录用户
+ */
+ String LOGIN_USER_INFO = "login_user_info";
+ /**
+ * 系列子类
+ */
+ String CLASSIFICATION_CHILD = "classification_child";
+ /**
+ * HouseFragment中的ViewPager
+ */
+ String HOUSE_FRAGMENT_VIEWPAGER = "viewpager";
+ /**
+ * 供应商 商品 信息
+ */
+ String VENDOR_GOODS_INFO = "vendor_goods_info";
+
+
+}
diff --git a/common_base/src/main/java/com/wss/common/constants/EventAction.java b/common_base/src/main/java/com/wss/common/constants/EventAction.java
new file mode 100644
index 0000000..267af44
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/constants/EventAction.java
@@ -0,0 +1,41 @@
+package com.wss.common.constants;
+
+/**
+ * Describe:EventBus事件
+ * Created by 吴天强 on 2018/10/19.
+ */
+public interface EventAction {
+
+ //************************************Common模块****************************************/
+ /**
+ * 删除画廊的图片, Action Data = 删除图片的position
+ */
+ String IMAGE_GALLERY_DELETE = "image_gallery_delete";
+ /**
+ * 二维码扫描结果 Action Data = String
+ */
+ String SCAN_QR_CODE_RESULT = "scan_qr_code_result";
+
+
+
+ //************************************Market模块*****************************************/
+ /**
+ * 购物车有变化
+ */
+ String EVENT_SHOPPING_CART_CHANGED = "event_shopping_cart_changed";
+ /**
+ * 刷新购物车 重新获取数据
+ */
+ String EVENT_SHOPPING_CART_REFRESH = "event_shopping_cart_refresh";
+
+ //************************************User模块*****************************************/
+ /**
+ * 登录成功
+ */
+ String EVENT_LOGIN_SUCCESS = "event_login_success";
+
+ /**
+ * 注册成功
+ */
+ String EVENT_REGISTER_SUCCESS = "event_register_success";
+}
diff --git a/common_base/src/main/java/com/wss/common/constants/EventConstant.java b/common_base/src/main/java/com/wss/common/constants/EventConstant.java
deleted file mode 100644
index 82925c3..0000000
--- a/common_base/src/main/java/com/wss/common/constants/EventConstant.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.wss.common.constants;
-
-/**
- * Describe:EventBus事件
- * Created by 吴天强 on 2018/10/19.
- */
-
-public interface EventConstant {
-
- /**
- * 商城商品被点击
- */
- String EVENT_MARKET_CLICK = "event_market_click";
-}
diff --git a/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java b/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java
new file mode 100644
index 0000000..5dfc8cb
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/dao/BaseDBManager.java
@@ -0,0 +1,111 @@
+package com.wss.common.dao;
+
+import org.greenrobot.greendao.AbstractDao;
+import org.greenrobot.greendao.query.QueryBuilder;
+
+import java.util.List;
+
+/**
+ * Describe:所有的数据库操作类都继承自此
+ * Created by 吴天强 on 2018/11/5.
+ */
+public class BaseDBManager {
+
+ private AbstractDao mDao;
+
+ public BaseDBManager(AbstractDao dao) {
+ this.mDao = dao;
+ }
+
+ public void insert(T item) {
+ mDao.insert(item);
+ }
+
+ public void insert(T... items) {
+ mDao.insertInTx(items);
+ }
+
+ public void insert(List items) {
+ mDao.insertInTx(items);
+ }
+
+ public void insertOrUpdate(T item) {
+ mDao.insertOrReplace(item);
+ }
+
+ public void insertOrUpdate(T... items) {
+ mDao.insertOrReplaceInTx(items);
+ }
+
+ public void insertOrUpdate(List items) {
+ mDao.insertOrReplaceInTx(items);
+ }
+
+ public void deleteByKey(K key) {
+ mDao.deleteByKey(key);
+ }
+
+ public void delete(T item) {
+ mDao.delete(item);
+ }
+
+ public void delete(T... items) {
+ mDao.deleteInTx(items);
+ }
+
+ public void delete(List items) {
+ mDao.deleteInTx(items);
+ }
+
+ public void deleteAll() {
+ mDao.deleteAll();
+ }
+
+ public void update(T item) {
+ mDao.update(item);
+ }
+
+ public void update(T... items) {
+ mDao.updateInTx(items);
+ }
+
+ public void update(List items) {
+ mDao.updateInTx(items);
+ }
+
+ /**
+ * 根据主键查询数据 如果没有涉及主键 则会报错
+ *
+ * @param key 主键
+ * @return T
+ */
+ public T query(K key) {
+ return mDao.load(key);
+ }
+
+ public List queryAll() {
+ return mDao.loadAll();
+ }
+
+ public List query(String where, String... params) {
+ return mDao.queryRaw(where, params);
+ }
+
+ public QueryBuilder getQueryBuilder() {
+ return mDao.queryBuilder();
+ }
+
+ public long count() {
+ return mDao.count();
+ }
+
+ public void refresh(T item) {
+ mDao.refresh(item);
+ }
+
+ public void detach(T item) {
+ mDao.detach(item);
+ }
+
+}
+
diff --git a/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java b/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java
new file mode 100644
index 0000000..b46cac6
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/dao/DBMigrationHelper.java
@@ -0,0 +1,240 @@
+package com.wss.common.dao;
+
+
+import android.database.Cursor;
+import android.database.SQLException;
+import android.database.sqlite.SQLiteDatabase;
+import android.text.TextUtils;
+
+import com.orhanobut.logger.Logger;
+
+import org.greenrobot.greendao.AbstractDao;
+import org.greenrobot.greendao.database.Database;
+import org.greenrobot.greendao.database.StandardDatabase;
+import org.greenrobot.greendao.internal.DaoConfig;
+import org.jetbrains.annotations.Contract;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+
+/**
+ * Describe:数据库升级操作类
+ * Created by 吴天强 on 2018/11/5.
+ */
+public class DBMigrationHelper {
+
+ private static final String SQLITE_MASTER = "sqlite_master";
+ private static final String SQLITE_TEMP_MASTER = "sqlite_temp_master";
+
+ static void migrate(SQLiteDatabase db, Class extends AbstractDao, ?>>... daoClasses) {
+ Logger.e("【The Old Database Version】" + db.getVersion());
+ Database database = new StandardDatabase(db);
+ migrate(database, daoClasses);
+ }
+
+
+ @SafeVarargs
+ static void migrate(Database database, Class extends AbstractDao, ?>>... daoClasses) {
+ Logger.e("【Generate temp table】start");
+ generateTempTables(database, daoClasses);
+ Logger.e("【Generate temp table】complete");
+
+ Logger.e("【Drop all table and recreate all table】");
+ for (Class extends AbstractDao, ?>> daoClass : daoClasses) {
+ DaoConfig daoConfig = new DaoConfig(database, daoClass);
+ dropTable(database, true, daoConfig);
+ createTable(database, false, daoConfig);
+ }
+
+ Logger.e("【Restore data】start");
+ restoreData(database, daoClasses);
+ Logger.e("【Restore data】complete");
+ }
+
+ private static void dropTable(Database database, boolean ifExists, DaoConfig daoConfig) {
+ String sql = String.format("DROP TABLE %s\"%s\"", ifExists ? "IF EXISTS " : "", daoConfig.tablename);
+ database.execSQL(sql);
+ }
+
+ @SafeVarargs
+ private static void generateTempTables(Database db, Class extends AbstractDao, ?>>... daoClasses) {
+ for (Class extends AbstractDao, ?>> daoClass : daoClasses) {
+ String tempTableName = null;
+
+ DaoConfig daoConfig = new DaoConfig(db, daoClass);
+ String tableName = daoConfig.tablename;
+ if (!isTableExists(db, false, tableName)) {
+ Logger.e("【New Table】" + tableName);
+ continue;
+ }
+ try {
+ tempTableName = daoConfig.tablename.concat("_TEMP");
+ StringBuilder dropTableStringBuilder = new StringBuilder();
+ dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";");
+ Logger.e("【Generate temp table】 dropTableStringBuilder:" + dropTableStringBuilder);
+ db.execSQL(dropTableStringBuilder.toString());
+
+ StringBuilder insertTableStringBuilder = new StringBuilder();
+ insertTableStringBuilder.append("CREATE TEMPORARY TABLE ").append(tempTableName);
+ insertTableStringBuilder.append(" AS SELECT * FROM ").append(tableName).append(";");
+ Logger.e("【Generate temp table】 insertTableStringBuilder:" + insertTableStringBuilder);
+ db.execSQL(insertTableStringBuilder.toString());
+ Logger.e("【Table】" + tableName + "\n ---Columns-->" + getColumnsStr(daoConfig));
+ Logger.e("【Generate temp table】" + tempTableName);
+ } catch (SQLException e) {
+ Logger.e("【Failed to generate temp table】" + tempTableName, e);
+ }
+ }
+ }
+
+ @Contract("null, _, _ -> false")
+ private static boolean isTableExists(Database db, boolean isTemp, String tableName) {
+ if (db == null || TextUtils.isEmpty(tableName)) {
+ return false;
+ }
+ String dbName = isTemp ? SQLITE_TEMP_MASTER : SQLITE_MASTER;
+ String sql = "SELECT COUNT(*) FROM " + dbName + " WHERE type = ? AND name = ?";
+ Cursor cursor = null;
+ int count = 0;
+ try {
+ cursor = db.rawQuery(sql, new String[]{"table", tableName});
+ if (cursor == null || !cursor.moveToFirst()) {
+ return false;
+ }
+ count = cursor.getInt(0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return count > 0;
+ }
+
+
+ private static String getColumnsStr(DaoConfig daoConfig) {
+ if (daoConfig == null) {
+ return "no columns";
+ }
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < daoConfig.allColumns.length; i++) {
+ builder.append(daoConfig.allColumns[i]);
+ builder.append(",");
+ }
+ if (builder.length() > 0) {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString();
+ }
+
+
+ @SafeVarargs
+ private static void restoreData(Database db, Class extends AbstractDao, ?>>... daoClasses) {
+ for (Class extends AbstractDao, ?>> daoClass : daoClasses) {
+ DaoConfig daoConfig = new DaoConfig(db, daoClass);
+ String tableName = daoConfig.tablename;
+ String tempTableName = daoConfig.tablename.concat("_TEMP");
+ isTableExists(db, true, tempTableName);
+ try {
+ // get all columns from tempTable, take careful to use the columns list
+ List columns = getColumns(db, tempTableName);
+ ArrayList properties = new ArrayList<>(columns.size());
+ for (int j = 0; j < daoConfig.properties.length; j++) {
+ String columnName = daoConfig.properties[j].columnName;
+ if (columns.contains(columnName)) {
+ properties.add(columnName);
+ }
+ }
+ if (properties.size() > 0) {
+ final String columnSQL = TextUtils.join(",", properties);
+
+ StringBuilder insertTableStringBuilder = new StringBuilder();
+ insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
+ insertTableStringBuilder.append(columnSQL);
+ insertTableStringBuilder.append(") SELECT ");
+ insertTableStringBuilder.append(columnSQL);
+ insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
+ Logger.e("【Restore data】 db sql: " + insertTableStringBuilder);
+ db.execSQL(insertTableStringBuilder.toString());
+ Logger.e("【Restore data】 to " + tableName);
+ }
+ StringBuilder dropTableStringBuilder = new StringBuilder();
+ dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
+ db.execSQL(dropTableStringBuilder.toString());
+ Logger.e("【Drop temp table】" + tempTableName);
+ } catch (SQLException e) {
+ Logger.e("【Failed to restore data from temp table 】" + tempTableName, e);
+ }
+ }
+ }
+
+ private static List getColumns(Database db, String tableName) {
+ List columns = null;
+ try (Cursor cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 0", null)) {
+ if (null != cursor && cursor.getColumnCount() > 0) {
+ columns = Arrays.asList(cursor.getColumnNames());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (null == columns) {
+ columns = new ArrayList<>();
+ }
+ }
+ return columns;
+ }
+
+ private static void createTable(Database db, boolean ifNotExists, DaoConfig daoConfig) {
+ String tableName = daoConfig.tablename;
+ StringBuilder builder = new StringBuilder();
+ builder.append("CREATE TABLE ");
+ builder.append(ifNotExists ? "IF NOT EXISTS " : "");
+ builder.append(tableName);
+ builder.append(getColumnsSql(daoConfig));
+ Logger.e("【createTable】 sql:" + builder.toString());
+ db.execSQL(builder.toString()); // 6: Description
+ }
+
+ private static String getColumnsSql(DaoConfig daoConfig) {
+ if (daoConfig == null) {
+ return "";
+ }
+ StringBuilder builder = new StringBuilder(" (");
+ for (int i = 0; i < daoConfig.properties.length; i++) {
+ builder.append(String.format("\"%s\" %s,", daoConfig.properties[i].columnName,
+ getPropertyType(daoConfig.properties[i].type)));
+ }
+ if (daoConfig.properties.length > 0 && builder.length() > 0) {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ builder.append("); ");
+ return builder.toString();
+ }
+
+ /**
+ * 根据字段类型返回对应的数据库字段语句
+ *
+ * @param type
+ * @return
+ */
+ private static String getPropertyType(Class> type) {
+ if (type.equals(byte[].class)) {
+ return "BLOB";
+ } else if (type.equals(String.class)) {
+ return "TEXT DEFAULT ''";
+ } else if (type.equals(boolean.class) || type.equals(Boolean.class)
+ || type.equals(int.class) || type.equals(Integer.class)
+ || type.equals(long.class) || type.equals(Long.class)
+ || type.equals(Date.class) || type.equals(Byte.class)) {
+ return "INTEGER DEFAULT (0)";
+ } else if (type.equals(float.class) || type.equals(Float.class)
+ || type.equals(double.class) || type.equals(Double.class)) {
+ return "REAL DEFAULT (0)";
+ }
+ return "TEXT DEFAULT ''";
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/exception/NetErrorException.java b/common_base/src/main/java/com/wss/common/exception/NetErrorException.java
new file mode 100644
index 0000000..deb20d6
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/exception/NetErrorException.java
@@ -0,0 +1,53 @@
+package com.wss.common.exception;
+
+/**
+ * Describe:网络请求异常类
+ * Created by 吴天强 on 2019/6/15.
+ */
+public class NetErrorException extends Exception {
+
+ /**
+ * 网络请求错误码
+ */
+ private String errorCode;
+ /**
+ * 响应的Data
+ */
+ private String responseData;
+
+ public NetErrorException() {
+ }
+
+ public NetErrorException(String message) {
+ this("", message);
+ }
+
+ public NetErrorException(String errorCode, String message) {
+ this(errorCode, message, "");
+
+ }
+
+ public NetErrorException(String errorCode, String message, String responseData) {
+ super(message);
+ this.errorCode = errorCode;
+ this.responseData = responseData;
+ }
+
+ /**
+ * 返回网络请求错误码
+ *
+ * @return errorCode
+ */
+ public String getNetErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * 返回网路响应的DATA
+ *
+ * @return responseData
+ */
+ public String getNetResponseData() {
+ return responseData;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java b/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java
deleted file mode 100644
index 958532e..0000000
--- a/common_base/src/main/java/com/wss/common/listener/OnListItemClickListener.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.wss.common.listener;
-
-/**
- * Describe:RecycleView 点击事件监听
- * Created by 吴天强 on 2018/10/18.
- */
-
-public interface OnListItemClickListener {
-
- void onItemClick(int position);
-}
diff --git a/common_base/src/main/java/com/wss/common/manage/ActivityManage.java b/common_base/src/main/java/com/wss/common/manage/ActivityManage.java
index 80b29d0..992ab1d 100644
--- a/common_base/src/main/java/com/wss/common/manage/ActivityManage.java
+++ b/common_base/src/main/java/com/wss/common/manage/ActivityManage.java
@@ -9,10 +9,11 @@
* Describe:管理所有的Activity
* Created by 吴天强 on 2018/10/15.
*/
-
public class ActivityManage {
- //保存所有创建的Activity
+ /**
+ * 保存所有创建的Activity
+ */
private Set allActivities = new HashSet<>();
/**
@@ -45,7 +46,5 @@ public void finishAll() {
for (Activity activity : allActivities) {
activity.finish();
}
-
}
-
}
diff --git a/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java b/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java
new file mode 100644
index 0000000..8d0a0af
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/manage/ActivityToActivity.java
@@ -0,0 +1,301 @@
+package com.wss.common.manage;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import com.alibaba.android.arouter.core.LogisticsCenter;
+import com.alibaba.android.arouter.facade.Postcard;
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.wss.common.base.bean.BaseBean;
+import com.wss.common.bean.Template;
+import com.wss.common.constants.Constants;
+import com.wss.common.constants.Dic;
+import com.wss.common.utils.ToastUtils;
+import com.wss.common.utils.Utils;
+import com.wss.common.view.browser.BrowserActivity;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import androidx.fragment.app.Fragment;
+
+/**
+ * Describe:Activity跳转
+ * Created by 吴天强 on 2018/10/22.
+ */
+public class ActivityToActivity {
+
+
+ ////////////////////////////////////////普通Activity跳转////////////////////////////////////////
+
+ /**
+ * 普通Activity之间跳转
+ *
+ * @param activity activity
+ * @param clazz 目标activity
+ */
+ public static void toActivity(Context activity, Class extends Activity> clazz) {
+ toActivityForResult(activity, clazz, null, 0);
+ }
+
+ /**
+ * 普通Activity之间跳转
+ *
+ * @param activity activity
+ * @param clazz 目标activity
+ * @param params 携带参数
+ */
+ public static void toActivity(Context activity, Class extends Activity> clazz, Map params) {
+ toActivityForResult(activity, clazz, params, 0);
+ }
+
+ /**
+ * 普通Activity之间跳转
+ *
+ * @param activity activity
+ * @param clazz 目标activity
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(Context activity, Class extends Activity> clazz, int requestCode) {
+ toActivityForResult(activity, clazz, null, requestCode);
+ }
+
+ /**
+ * 普通Activity之间跳转
+ * ps:兼容从Fragment中使用ActivityForResult。传统方式Fragment中的onActivityResult中无法收到回调
+ *
+ * @param fragment 当前fragment
+ * @param activity activity
+ * @param clazz 目标activity
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(Fragment fragment, Context activity, Class extends Activity> clazz, int requestCode) {
+ toActivityForResult(fragment, activity, clazz, null, requestCode);
+ }
+
+ /**
+ * 普通Activity之间跳转
+ *
+ * @param activity activity
+ * @param clazz 目标activity
+ * @param params 参数
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(Context activity, Class extends Activity> clazz, Map params, int requestCode) {
+ Intent intent = new Intent();
+ intent.setClass(activity, clazz);
+ assembleParams(intent, params);
+ if (requestCode > 0) {
+ ((Activity) activity).startActivityForResult(intent, requestCode);
+ } else {
+ activity.startActivity(intent);
+ }
+ }
+
+ /**
+ * 在Fragment中调用startActivityForResult
+ *
+ * @param fragment 跳转所在的Fragment
+ * @param activity activity
+ * @param clazz 目标activity
+ * @param params 参数
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(@NotNull Fragment fragment, Context activity, Class extends Activity> clazz, Map params, int requestCode) {
+ Intent intent = new Intent();
+ intent.setClass(activity, clazz);
+ assembleParams(intent, params);
+ fragment.startActivityForResult(intent, requestCode);
+ }
+
+ private static void assembleParams(Intent intent, Map params) {
+ if (params != null) {
+ for (Map.Entry entry : params.entrySet()) {
+ String key = entry.getKey();
+ Object value = params.get(key);
+ if (value instanceof String) {
+ intent.putExtra(key, (String) value);
+ } else if (value instanceof Boolean) {
+ intent.putExtra(key, (boolean) value);
+ } else if (value instanceof Integer) {
+ intent.putExtra(key, (int) value);
+ } else if (value instanceof Float) {
+ intent.putExtra(key, (float) value);
+ } else if (value instanceof Double) {
+ intent.putExtra(key, (double) value);
+ } else if (value instanceof Long) {
+ intent.putExtra(key, (long) value);
+ } else if (value instanceof Short) {
+ intent.putExtra(key, (short) value);
+ } else if (value instanceof Bundle) {
+ intent.putExtra(key, (Bundle) value);
+ } else if (value instanceof BaseBean) {
+ intent.putExtra(key, (BaseBean) value);
+ } else if (value instanceof ArrayList) {
+ intent.putExtra(key, (ArrayList) value);
+ } else if (value instanceof HashMap) {
+ intent.putExtra(key, (HashMap) value);
+ }
+ }
+ }
+ }
+ //////////////////////////////////////WebView跳转//////////////////////////////////////
+
+ /**
+ * 跳转WebView url 不可为空
+ *
+ * @param context context
+ * @param url 链接
+ * @param title 标题
+ */
+ public static void toWebView(Context context, String url, String title) {
+// if (!NetworkUtil.isLink(url)) {
+// return;
+// }
+ Map param = new HashMap<>();
+ param.put(Dic.URL, url);
+ param.put(Dic.TITLE_TEXT, title);
+ toActivity(context, BrowserActivity.class, param);
+ }
+
+ /**
+ * 跳转WebView url 不可为空
+ *
+ * @param context 链接
+ * @param url 标题
+ */
+ public static void toWebView(Context context, String url) {
+ toWebView(context, url, "");
+ }
+
+ //////////////////////////////////////ARouter跳转//////////////////////////////////////
+
+ /**
+ * ARouter跳转Activity
+ *
+ * @param activity Activity
+ * @param url 目标Activity Url
+ */
+ public static void toActivity(Activity activity, String url) {
+ toActivityForResult(activity, url, null, 0);
+ }
+
+ /**
+ * ARouter跳转Activity
+ *
+ * @param activity Activity
+ * @param url 目标Activity Url
+ */
+ public static void toActivity(Activity activity, String url, Map params) {
+ toActivityForResult(activity, url, params, 0);
+ }
+
+ /**
+ * ARouter跳转Activity
+ *
+ * @param activity Activity
+ * @param url 目标Activity Url
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(Activity activity, String url, int requestCode) {
+ toActivityForResult(activity, url, null, requestCode);
+ }
+
+ /**
+ * ARouter跳转Activity
+ *
+ * @param activity Activity
+ * @param url 目标Activity Url
+ * @param params 参数
+ * @param requestCode 请求码 需大于0
+ */
+ public static void toActivityForResult(Activity activity, String url, Map params, int requestCode) {
+ if (TextUtils.isEmpty(url)) {
+ return;
+ }
+ Postcard postcard = ARouter.getInstance()
+ .build(url);
+// .withOptionsCompat(ActivityOptionsCompat.makeCustomAnimation(activity, R.anim.anim_right_in, R.anim.anim_right_out));
+ if (params != null) {
+ for (Map.Entry entry : params.entrySet()) {
+ String key = entry.getKey();
+ Object value = params.get(key);
+ if (value instanceof String) {
+ postcard.withString(key, (String) value);
+ } else if (value instanceof Boolean) {
+ postcard.withBoolean(key, (boolean) value);
+ } else if (value instanceof Integer) {
+ postcard.withInt(key, (int) value);
+ } else if (value instanceof Float) {
+ postcard.withFloat(key, (float) value);
+ } else if (value instanceof Double) {
+ postcard.withDouble(key, (double) value);
+ } else if (value instanceof Long) {
+ postcard.withLong(key, (long) value);
+ } else if (value instanceof Short) {
+ postcard.withShort(key, (short) value);
+ } else if (value instanceof Bundle) {
+ postcard.withBundle(key, (Bundle) value);
+ } else if (value instanceof BaseBean) {
+ postcard.withSerializable(key, (BaseBean) value);
+ } else if (value instanceof ArrayList) {
+ postcard.withSerializable(key, (ArrayList) value);
+ } else if (value instanceof HashMap) {
+ postcard.withSerializable(key, (HashMap) value);
+ }
+ }
+ }
+ if (requestCode > 0) {
+ LogisticsCenter.completion(postcard);
+ activity.startActivityForResult(new Intent(activity, postcard.getDestination()), requestCode);
+ } else {
+ postcard.navigation();
+ }
+ }
+
+
+ /**
+ * 通过模板跳转Activity
+ *
+ * @param activity activity
+ * @param template 模板信息
+ */
+ @SuppressWarnings("unchecked")
+ public static void toActivity(Activity activity, Template template) {
+ switch (template.getType()) {
+ case Constants.TemplateType.ACTIVITY:
+ //跳转Activity
+ toActivity(activity, template.getClazz(), template.getParams());
+ break;
+ case Constants.TemplateType.AROUTER:
+ //跳转Arouter
+ toActivity(activity, template.getUrl(), template.getParams());
+ break;
+ case Constants.TemplateType.WEB_VIEW:
+ //跳转WebView
+ toWebView(activity, template.getUrl(), template.getDescribe());
+ break;
+ case Constants.TemplateType.SYS_BROWSER:
+ //跳转手机浏览器
+ Utils.toSystemBrowser(activity, template.getUrl());
+ break;
+ default:
+
+ }
+ }
+
+ /**
+ * 跳转登录页
+ *
+ * @param context ctx
+ */
+ public static void toLoginActivity(Context context) {
+ ToastUtils.show("跳转登录页");
+ }
+}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java b/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java
new file mode 100644
index 0000000..027edee
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/manage/BlurTransformation.java
@@ -0,0 +1,88 @@
+package com.wss.common.manage;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Build;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
+
+import java.security.MessageDigest;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Describe:加载图片转换器之模糊转换器
+ * Created by 吴天强 on 2018/11/8.
+ */
+public class BlurTransformation extends BitmapTransformation {
+ private Context context;
+ /**
+ * 模糊度 0=< blurRadius<=25
+ */
+ private float blurRadius = 15;
+
+ public BlurTransformation(Context context) {
+ this.context = context;
+ }
+
+ /**
+ * @param context context
+ * @param blurRadius 模糊度 最大25
+ */
+ public BlurTransformation(Context context, float blurRadius) {
+ this.context = context;
+ this.blurRadius = blurRadius;
+ }
+
+ @Override
+ protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
+ return blurBitmap(context, toTransform, outWidth, outHeight);
+ }
+
+ @Override
+ public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
+ }
+
+
+ /**
+ * @param context 上下文对象
+ * @param image 需要模糊的图片
+ * @param outWidth 输入出的宽度
+ * @param outHeight 输出的高度
+ * @return 模糊处理后的Bitmap
+ */
+ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
+ private Bitmap blurBitmap(Context context, Bitmap image, int outWidth, int outHeight) {
+ // 将缩小后的图片做为预渲染的图片
+ Bitmap inputBitmap = Bitmap.createScaledBitmap(image, outWidth, outHeight, false);
+ // 创建一张渲染后的输出图片
+ Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
+ // 创建RenderScript内核对象
+ RenderScript rs = RenderScript.create(context);
+ // 创建一个模糊效果的RenderScript的工具对象
+ ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
+ // 由于RenderScript并没有使用VM来分配内存,所以需要使用Allocation类来创建和分配内存空间
+ // 创建Allocation对象的时候其实内存是空的,需要使用copyTo()将数据填充进去
+ Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
+ Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
+ // 设置渲染的模糊程度, 25f是最大模糊度
+ //模糊度最大到25
+ if (blurRadius < 0 || blurRadius > 25) {
+ blurRadius = 20;
+ }
+ blurScript.setRadius(blurRadius);
+ // 设置blurScript对象的输入内存
+ blurScript.setInput(tmpIn);
+ // 将输出数据保存到输出内存中
+ blurScript.forEach(tmpOut);
+ // 将数据填充到Allocation中
+ tmpOut.copyTo(outputBitmap);
+ return outputBitmap;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java b/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java
deleted file mode 100644
index f14f11f..0000000
--- a/common_base/src/main/java/com/wss/common/manage/CrashHandlerManage.java
+++ /dev/null
@@ -1,187 +0,0 @@
-package com.wss.common.manage;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.Build;
-import android.os.Environment;
-import android.support.annotation.Nullable;
-
-import com.orhanobut.logger.Logger;
-import com.wss.common.base.BaseApplication;
-import com.wss.common.utils.DateUtils;
-import com.wss.common.utils.FileUtils;
-import com.wss.common.utils.ZipUtils;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-
-/**
- * UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告.
- */
-@SuppressLint("StaticFieldLeak")
-public class CrashHandlerManage implements UncaughtExceptionHandler {
- private static final String TAG = "CrashHandlerManage";
- private UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类
- private static CrashHandlerManage INSTANCE;
- private Context mContext;// 程序的Context对象
- private Map info = new HashMap<>();// 用来存储设备信息和异常信息
-
- /**
- * 保证只有一个CrashHandler实例
- */
- private CrashHandlerManage() {
- }
-
- public synchronized static CrashHandlerManage getInstance() {
- if (INSTANCE == null) {
- INSTANCE = new CrashHandlerManage();
- }
- return INSTANCE;
- }
-
-
- /**
- * 初始化
- */
- public void init(Context context) {
- mContext = context;
- mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器
- Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器
- }
-
- /**
- * 当UncaughtException发生时会转入该重写的方法来处理
- */
- public void uncaughtException(Thread thread, Throwable ex) {
- if (!handleException(ex) && mDefaultHandler != null) {
- // 如果自定义的没有处理则让系统默认的异常处理器来处理
- mDefaultHandler.uncaughtException(thread, ex);
- } else {
- try {
- Thread.sleep(3000);// 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- ((BaseApplication) mContext.getApplicationContext()).exitApp();
- // 退出程序
- android.os.Process.killProcess(android.os.Process.myPid());
- System.exit(1);
- }
- }
-
- /**
- * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
- *
- * @param ex 异常信息
- * @return true 如果处理了该异常信息;否则返回false.
- */
- public boolean handleException(Throwable ex) {
- if (ex == null)
- return false;
- // 收集设备参数信息
- collectDeviceInfo(mContext);
- // 保存日志文件
- saveCrashInfo2File(ex);
- return true;
- }
-
- /**
- * 收集设备参数信息
- */
- public void collectDeviceInfo(Context context) {
- try {
- PackageManager pm = context.getPackageManager();// 获得包管理器
- PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
- PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity
- if (pi != null) {
- String versionName = pi.versionName == null ? "null"
- : pi.versionName;
- String versionCode = pi.versionCode + "";
- info.put("versionName", versionName);
- info.put("versionCode", versionCode);
- }
- } catch (NameNotFoundException e) {
- e.printStackTrace();
- Logger.e("获取设置信息失败");
- }
-
- Field[] fields = Build.class.getDeclaredFields();// 反射机制
- for (Field field : fields) {
- try {
- field.setAccessible(true);
- info.put(field.getName(), field.get("").toString());
- Logger.e(field.getName() + ":" + field.get(""));
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- }
-
- @Nullable
- private String saveCrashInfo2File(Throwable ex) {
- StringBuilder sb = new StringBuilder();
- for (Map.Entry entry : info.entrySet()) {
- String key = entry.getKey();
- String value = entry.getValue();
- sb.append(key).append("=").append(value).append("\r\n");
- }
- Writer writer = new StringWriter();
- PrintWriter pw = new PrintWriter(writer);
- ex.printStackTrace(pw);
- Throwable cause = ex.getCause();
- // 循环着把所有的异常信息写入writer中
- while (cause != null) {
- cause.printStackTrace(pw);
- cause = cause.getCause();
- }
- pw.close();// 记得关闭
- String result = writer.toString();
- sb.append(result);
- // 保存文件
- String fileName = "crash-" + DateUtils.getCurrentDateStr() + "-" + DateUtils.getCurrentTimeStamp() + ".log";
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- try {
- File file = new File(FileUtils.getAppCrashPath(), fileName);
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(sb.toString().getBytes());
- fos.close();
- return fileName;
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return null;
- }
-
- /**
- * 上传日志文件
- */
- public static void uploadCrashFiles() {
- final File outFile = FileUtils.getAppCrashPath();
- LinkedList files = FileUtils.listLinkedFiles(FileUtils.getAppCrashPath().getPath());
- if (files == null || files.size() == 0) {
- return;
- }
- try {
- ZipUtils.zipFiles(files, outFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (!outFile.exists()) {//如果这个zip文件不存在的话,则不执行如下的操作
- return;
- }
- //TODO 做上传操作
- }
-}
diff --git a/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java b/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java
new file mode 100644
index 0000000..dcd825c
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/manage/GlideRoundTransform.java
@@ -0,0 +1,60 @@
+package com.wss.common.manage;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
+import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
+import com.wss.common.utils.PxUtils;
+
+import org.jetbrains.annotations.Contract;
+
+import java.security.MessageDigest;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Describe:加载图片转换器之圆角转换器
+ * Created by 吴天强 on 2019/7/2.
+ */
+public class GlideRoundTransform extends BitmapTransformation {
+
+ private float radius = 0f;
+
+ public GlideRoundTransform(Context context, int dp) {
+ super();
+ radius = PxUtils.dp2px(dp);
+ }
+
+ @Override
+ protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
+ Bitmap bitmap = TransformationUtils.centerCrop(pool, toTransform, outWidth, outHeight);
+ return roundCrop(pool, bitmap);
+ }
+
+ @Contract("_, null -> null")
+ private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
+ if (source == null){ return null;}
+ Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(result);
+ Paint paint = new Paint();
+ paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
+ paint.setAntiAlias(true);
+ RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
+ canvas.drawRoundRect(rectF, radius, radius, paint);
+ return result;
+ }
+
+ public String getId() {
+ return getClass().getName() + Math.round(radius);
+ }
+
+ @Override
+ public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/manage/MediaScannerManage.java b/common_base/src/main/java/com/wss/common/manage/MediaScannerManage.java
new file mode 100644
index 0000000..c09c792
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/manage/MediaScannerManage.java
@@ -0,0 +1,74 @@
+package com.wss.common.manage;
+
+import android.content.Context;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * Describe:扫描媒体文件帮助类(主要用户保存文件、图片之后刷新到相册 操作)
+ * Created by 吴天强 on 2021/5/10.
+ */
+public class MediaScannerManage {
+
+ private MediaScannerConnection mConn = null;
+ private File mFile = null;
+
+ private MediaScannerManage(Context context) {
+ ScannerClient mClient = new ScannerClient();
+ if (mConn == null) {
+ mConn = new MediaScannerConnection(context, mClient);
+ }
+ }
+
+ @NotNull
+ @Contract("_ -> new")
+ public static synchronized MediaScannerManage getInstance(Context context) {
+ return new MediaScannerManage(context);
+ }
+
+
+ public void scanFile(File file) {
+ mFile = file;
+ mConn.connect();
+ }
+
+ private class ScannerClient implements MediaScannerConnection.MediaScannerConnectionClient {
+
+ @Override
+ public void onMediaScannerConnected() {
+ if (mFile == null) {
+ return;
+ }
+ scan(mFile);
+ }
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+ mConn.disconnect();
+ }
+
+ private void scan(@NotNull File file) {
+
+ if (file.isFile()) {
+ mConn.scanFile(file.getAbsolutePath(), null);
+ return;
+ }
+ File[] files = file.listFiles();
+ if (files == null) {
+ return;
+ }
+ File[] files1 = file.listFiles();
+ if (files1 == null) {
+ return;
+ }
+ for (File f : files1) {
+ scan(f);
+ }
+ }
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java b/common_base/src/main/java/com/wss/common/manage/UpdateManager.java
deleted file mode 100644
index dcf0cd5..0000000
--- a/common_base/src/main/java/com/wss/common/manage/UpdateManager.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package com.wss.common.manage;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Message;
-import android.text.TextUtils;
-import android.view.View;
-import android.widget.ProgressBar;
-
-import com.tamic.novate.Throwable;
-import com.tamic.novate.callback.RxFileCallBack;
-import com.wss.common.base.BaseApplication;
-import com.wss.common.base.R;
-import com.wss.common.net.HttpUtils;
-import com.wss.common.utils.FileUtils;
-import com.wss.common.utils.ToastUtils;
-import com.wss.common.widget.dialog.AppDialog;
-
-import java.io.File;
-
-
-/**
- * 更新下载APK
- * Created by wtq on 2016/7/22.
- */
-@SuppressLint("StaticFieldLeak")
-public class UpdateManager {
-
- private static final int DOWNLOADING = 0x00;
- private static final int DOWNLOAD_SUCCESS = 0x02;
- private static final int DOWNLOAD_FAILED = 0x03;
- private static final int DOWNLOAD_CANCEL = 0x04;
- private static String DOWNLOAD_PATH = "/updateApkFile/";
- private static String APK_NAME = BaseApplication.getApplication().getPackageName() + "Temp.apk";
- /**
- * 下载之后存放路径
- */
- private String apkPath = FileUtils.getTempPath() + DOWNLOAD_PATH + APK_NAME;
-
- private Context mContext;
- private ProgressBar progressBar;
- private AppDialog dialog;
- private static UpdateManager manager;
- private String downloadUrl;
-
- private UpdateManager(Context context) {
- this.mContext = context;
- //每次启动先删除本地原有APK
- FileUtils.deleteFile(apkPath);
- }
-
- public static synchronized UpdateManager getInstance(Context context) {
- if (manager == null) {
- manager = new UpdateManager(context);
- }
- return manager;
- }
-
- /**
- * 设置下载地址
- *
- * @param url url
- * @return UpdateManager
- */
- public UpdateManager setDownloadUrl(String url) {
- this.downloadUrl = url;
- return this;
- }
-
- /**
- * 弹出下载框
- */
- public void download() {
- if (TextUtils.isEmpty(downloadUrl)) {
- ToastUtils.showToast(mContext, "请设置下载Url");
- return;
- }
-
- View progressBarView = View.inflate(mContext, R.layout.laytou_update_progress, null);
- progressBar = progressBarView.findViewById(R.id.pb_update_progress);
- dialog = new AppDialog(mContext);
- dialog.setTitle("版本更新中···")
- .addContentView(progressBarView)
- .setSingleButton("后台下载", new AppDialog.OnButtonClickListener() {
- @Override
- public void onClick(String val) {
- ToastUtils.showToast(mContext, "已切换到后台下载···");
- }
- })
- .show();
- HttpUtils.getInstance(mContext)
- .downloadFile(downloadUrl, new RxFileCallBack(apkPath, "Temp.apk") {
-
- @Override
- public void onNext(Object tag, File file) {
- updateHandler.sendEmptyMessage(DOWNLOAD_SUCCESS);
- }
-
- @Override
- public void onProgress(Object tag, float progress, long downloaded, long total) {
- Message message = updateHandler.obtainMessage();
- message.what = DOWNLOADING;
- message.obj = (int) progress;
- updateHandler.sendMessage(message);
- }
-
- @Override
- public void onError(Object tag, Throwable e) {
- updateHandler.sendEmptyMessage(DOWNLOAD_FAILED);
- }
-
- @Override
- public void onCancel(Object tag, Throwable e) {
- updateHandler.sendEmptyMessage(DOWNLOAD_CANCEL);
- }
- });
- }
-
-
- @SuppressLint("HandlerLeak")
- private Handler updateHandler = new Handler() {
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case DOWNLOADING:
- progressBar.setProgress((Integer) msg.obj);
- break;
- case DOWNLOAD_SUCCESS:
- dialog.dismiss();
- installApk();
- break;
- case DOWNLOAD_FAILED:
- dialog.dismiss();
- ToastUtils.showToast(mContext, "下载失败");
- break;
- case DOWNLOAD_CANCEL:
- dialog.dismiss();
- ToastUtils.showToast(mContext, "已取消下载");
- break;
- default:
- break;
- }
- }
-
- };
-
- /**
- * 安装apk
- */
- private void installApk() {
- // 安装,如果签名不一致,可能出现程序未安装提示
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setDataAndType(Uri.fromFile(new File(apkPath)), "application/vnd.android.package-archive");
- mContext.startActivity(intent);
- }
-}
diff --git a/common_base/src/main/java/com/wss/common/net/Api.java b/common_base/src/main/java/com/wss/common/net/Api.java
index a3d0583..7eff724 100644
--- a/common_base/src/main/java/com/wss/common/net/Api.java
+++ b/common_base/src/main/java/com/wss/common/net/Api.java
@@ -1,12 +1,22 @@
package com.wss.common.net;
+
+import com.wss.common.profile.ProfileManager;
+
+import rxhttp.wrapper.annotation.DefaultDomain;
+
/**
- * Describe:接口
+ * Describe:接口名称
* Created by 吴天强 on 2018/10/17.
*/
-
public interface Api {
+ /**
+ * 网络请求BaseUrl
+ */
+ @DefaultDomain
+ String BASE_URL = ProfileManager.profile().getServiceBase();
+ //**********************************************鸿洋开放接口**************************************
/**
* 获取Banner
*/
@@ -17,8 +27,71 @@ public interface Api {
*/
String GET_ARTICLE_LIST = "/article/list/%s/json";
+
+ /**
+ * 登录
+ */
+ String LOGIN = "/user/login";
+ /**
+ * 注册
+ */
+ String REGISTER = "/user/register";
+
+ /**
+ * 体系
+ */
+ String TREE = "/tree/json";
+ /**
+ * 体系下文章
+ */
+ String TREE_ARTICLE = "/article/list/%s/json?cid=%s";
+
+ /**
+ * 项目分类
+ */
+ String PROJECT = "/project/tree/json";
+
+ /**
+ * 项目列表
+ */
+ String PROJECT_LIST = "/project/list/%s/json?cid=%s";
+
+ /**
+ * 查询公众号列表
+ */
+ String WX_NUMBER = "/wxarticle/chapters/json";
+ /**
+ * 查询公众号文章
+ */
+ String WX_ARTICLE_LIST = "/wxarticle/list/%s/%s/json";
+
+ /**
+ * 搜索
+ */
+ String SEARCH_LIST = "/article/query/%s/json?k=%s";
+
+ /**
+ * 收藏列表
+ */
+ String COLLECTION_LIST = "/lg/collect/list/%s/json";
+
+
+ //**********************************************鸿洋开放接口**************************************
+
+
+ //**********************************************其他服务接口************************************
+
/**
- * 下载文件
+ * 上传文件(替换成自己的服务接口地址)
*/
- String DOWNLOAD_FILE = "http://wap.dl.pinyin.sogou.com/wapdl/hole/201512/03/SogouInput_android_v7.11_sweb.apk";
+ String UPLOAD_FILE = "/app/upload/uploadFile.json";
+
+ /**
+ * 下载文件(替换成自己的服务接口地址)
+ */
+ String DOWNLOAD_FILE = "/app/download/downloadFile.json";
+
+ //**********************************************其他服务接口************************************
+
+
}
diff --git a/common_base/src/main/java/com/wss/common/net/HttpUtils.java b/common_base/src/main/java/com/wss/common/net/HttpUtils.java
deleted file mode 100644
index 4aa4899..0000000
--- a/common_base/src/main/java/com/wss/common/net/HttpUtils.java
+++ /dev/null
@@ -1,289 +0,0 @@
-package com.wss.common.net;
-
-import android.content.Context;
-
-import com.orhanobut.logger.Logger;
-import com.tamic.novate.Novate;
-import com.tamic.novate.callback.ResponseCallback;
-import com.tamic.novate.callback.RxFileCallBack;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * Describe:网络请求帮助类
- * Created by 吴天强 on 2017/9/19.
- */
-
-public class HttpUtils {
-
- private static final int REQUEST_GET = 0;
- private static final int REQUEST_POST = 1;
- private static final int REQUEST_JSON = 2;
- private Novate.Builder builder;
- private static HttpUtils httpUtils;
-
- private HttpUtils(Context context) {
- builder = new Novate.Builder(context);
- builder.baseUrl(NetConfig.Url.getBaseUrl());
-
- //https配置 xxx.cer放在asset目录下
-// builder.skipSSLSocketFactory(true);//信任所有证书
-// builder.addSSLSocketFactory(NovateHttpsFactroy.creatSSLSocketFactory(
-// BaseApplication.getApplication().getBaseContext(), "xxx.cer"));
-
-// builder.addHeader(headers); //添加公共请求头
-// builder.addParameters(parameters);//公共参数
-// builder.connectTimeout(10); //连接时间 可以忽略
-// builder.addCookie(false); //是否同步cooike 默认不同步
-// builder.addCache(true); //是否缓存 默认缓存
-// builder.addCache(cache, cacheTime); //自定义缓存
-// builder.addLog(true);//是否开启log
-// builder.cookieManager(new NovateCookieManager()); // 自定义cooike,可以忽略
-// builder.addInterceptor(); // 自定义Interceptor
-// builder.addNetworkInterceptor(); // 自定义NetworkInterceptor
-// builder.proxy(proxy); //代理
-// builder.client(client); //clent 默认不需要
- }
-
- public static synchronized HttpUtils getInstance(Context context) {
- if (httpUtils == null) {
- httpUtils = new HttpUtils(context);
- }
- return httpUtils;
- }
-
-
- ////////////////////////////////////////// GET请求 /////////////////////////////////////////////
-
- /**
- * Get无参无Tag
- *
- * @param url 请求地址
- * @param callback 回调
- */
- public void getRequest(String url, ResponseCallback callback) {
- request(REQUEST_GET, url, new RequestParam(), null, callback);
- }
-
- /**
- * Get 无参有Tag
- *
- * @param url 请求地址
- * @param tag 标签
- * @param callback 回调
- */
- public void getRequest(String url, String tag, ResponseCallback callback) {
- request(REQUEST_GET, url, new RequestParam(), tag, callback);
- }
-
- /**
- * Get有参无Tag
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param callback 回调
- */
- public void getRequest(String url, RequestParam params, ResponseCallback callback) {
- request(REQUEST_GET, url, params, null, callback);
- }
-
- /**
- * Get有参有Tag
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param tag 标签
- * @param callback 回调
- */
- public void getRequest(String url, RequestParam params, String tag, ResponseCallback callback) {
- request(REQUEST_GET, url, params, tag, callback);
- }
-
-
- ////////////////////////////////////////// POST请求 /////////////////////////////////////////////
-
- /**
- * Post 无参无TAG
- *
- * @param url 请求地址
- * @param callback 回调
- */
- public void postRequest(String url, ResponseCallback callback) {
- request(REQUEST_POST, url, new RequestParam(), null, callback);
- }
-
- /**
- * Post 无参有TAG
- *
- * @param url 请求地址
- * @param tag 标签
- * @param callback 回调
- */
- public void postRequest(String url, String tag, ResponseCallback callback) {
- request(REQUEST_POST, url, new RequestParam(), tag, callback);
- }
-
- /**
- * Post 有参无TAG
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param callback 回调
- */
- public void postRequest(String url, RequestParam params, ResponseCallback callback) {
- request(REQUEST_POST, url, params, null, callback);
- }
-
- /**
- * Post 有参有TAG
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param tag 标签
- * @param callback 回调
- */
- public void postRequest(String url, RequestParam params, String tag, ResponseCallback callback) {
- request(REQUEST_POST, url, params, tag, callback);
- }
-
- ////////////////////////////////////////// JSON格式请求 /////////////////////////////////////////////
-
- /**
- * Post 无参无TAG
- *
- * @param url 请求地址
- * @param callback 回调
- */
- public void jsonRequest(String url, ResponseCallback callback) {
- request(REQUEST_JSON, url, new RequestParam(), null, callback);
- }
-
- /**
- * Post 无参有TAG
- *
- * @param url 请求地址
- * @param tag 标签
- * @param callback 回调
- */
- public void jsonRequest(String url, String tag, ResponseCallback callback) {
- request(REQUEST_JSON, url, new RequestParam(), tag, callback);
- }
-
- /**
- * Post 有参无TAG
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param callback 回调
- */
- public void jsonRequest(String url, RequestParam params, ResponseCallback callback) {
- request(REQUEST_JSON, url, params, null, callback);
- }
-
- /**
- * Post 有参有TAG
- *
- * @param url 请求地址
- * @param params 请求参数
- * @param tag 标签
- * @param callback 回调
- */
- public void jsonRequest(String url, RequestParam params, String tag, ResponseCallback callback) {
- request(REQUEST_JSON, url, params, tag, callback);
- }
-
-
- /**
- * 最终请求
- *
- * @param methodType 请求类型 get post
- * @param url 接口
- * @param params 参数
- * @param tag tag
- * @param callback 请求回调
- */
- private void request(int methodType, String url, RequestParam params, String tag, ResponseCallback callback) {
- Logger.e(NetConfig.Url.getBaseUrl() + url + params.toJson());
-// builder.header("");
- switch (methodType) {
- case REQUEST_POST:
- builder.build().rxPost(tag, url, params.getParameter(), callback);
- break;
- case REQUEST_GET:
- builder.build().rxGet(tag, url, params.getParameter(), callback);
- break;
- case REQUEST_JSON:
- builder.build().rxJson(tag, url, params.toJson(), callback);
- break;
- default:
- builder.build().rxGet(tag, url, params.getParameter(), callback);
- break;
- }
- }
-
- /**
- * 上传单个文件
- *
- * @param url 接口
- * @param file 文件
- * @param callback 回调
- */
- public void upLoadFile(String url, File file, ResponseCallback callback) {
- upLoadFile(url, file, null, callback);
- }
-
- /**
- * 上传单个文件
- *
- * @param url 接口
- * @param file 文件
- * @param tag 标签
- * @param callback 回调
- */
- public void upLoadFile(String url, File file, String tag, ResponseCallback callback) {
- //使用Part 方式上传文件
- Logger.e(NetConfig.Url.getBaseUrl() + url + file.getAbsolutePath());
- builder.build().rxUploadWithPart(url, file, callback);
- }
-
- /**
- * 上传多个文件
- *
- * @param url 接口
- * @param files 文件
- * @param callback 回调
- */
- public void upLoadFile(String url, List files, ResponseCallback callback) {
- upLoadFile(url, files, null, callback);
- }
-
-
- /**
- * 上传多个文件
- *
- * @param url 接口
- * @param files 文件
- * @param tag 标签
- * @param callback 回调
- */
- public void upLoadFile(String url, List files, String tag, ResponseCallback callback) {
- builder.build().rxUploadWithPartListByFile(tag, url, files, callback);
- }
-
- /**
- * 文件下载
- *
- * @param url 文件路径
- * @param callBack 回调
- */
- public void downloadFile(String url, RxFileCallBack callBack) {
- builder.build().rxDownload(url, callBack);
- }
-
-
- private boolean judgeUrl(String url) {
- return url.startsWith("http://") || url.startsWith("https://");
- }
-
-}
diff --git a/common_base/src/main/java/com/wss/common/net/NetConfig.java b/common_base/src/main/java/com/wss/common/net/NetConfig.java
deleted file mode 100644
index 8d8f360..0000000
--- a/common_base/src/main/java/com/wss/common/net/NetConfig.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.wss.common.net;
-
-import com.wss.common.constants.Constant;
-
-
-/**
- * Describe:网络请求URL
- * Created by 吴天强 on 2017/9/26.
- */
-
-public class NetConfig {
-
-
- /**
- * 响应的返回key
- */
- public class Code {
- public static final String SUCCESS = "success";
- public static final String MSG = "errorMsg";
- public static final String CODE = "errorCode";
- public static final String MODEL = "data";
- }
-
- /**
- * H5界面
- */
- public class Html {
-
- }
-
- /**
- * 网络请求Url
- */
- public static class Url {
-
-
- //服务器地址
- interface BaseUrl {
- String SERVER_DEVELOP = "http://www.wanandroid.com";
- String SERVER_TEST = "";
- String SERVER_PRODUCTION = "";
- }
-
- /**
- * 返回服务器基础地址
- */
- static String getBaseUrl() {
- switch (Constant.SERVER_TYPE) {
- case Constant.ServerType.SERVER_DEVELOP:
- return BaseUrl.SERVER_DEVELOP;
- case Constant.ServerType.SERVER_TEST:
- return BaseUrl.SERVER_TEST;
- case Constant.ServerType.SERVER_PRODUCTION:
- return BaseUrl.SERVER_PRODUCTION;
- }
- return BaseUrl.SERVER_PRODUCTION;
- }
-
-
- }
-
-}
diff --git a/common_base/src/main/java/com/wss/common/net/NetworkManage.java b/common_base/src/main/java/com/wss/common/net/NetworkManage.java
new file mode 100644
index 0000000..c8ff90c
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/net/NetworkManage.java
@@ -0,0 +1,617 @@
+package com.wss.common.net;
+
+import android.os.Handler;
+import android.text.TextUtils;
+
+import com.orhanobut.logger.Logger;
+import com.rxjava.rxlife.RxLife;
+import com.wss.common.base.BaseApplication;
+import com.wss.common.base.R;
+import com.wss.common.constants.Constants;
+import com.wss.common.exception.NetErrorException;
+import com.wss.common.manage.ActivityToActivity;
+import com.wss.common.net.request.RequestParam;
+import com.wss.common.net.response.BaseResponse;
+import com.wss.common.net.response.DownloadResponse;
+import com.wss.common.profile.ProfileManager;
+import com.wss.common.secret.AesUtils;
+import com.wss.common.utils.JsonUtils;
+import com.wss.common.utils.NetworkUtil;
+import com.wss.common.utils.ToastUtils;
+import com.wss.common.utils.Utils;
+import com.wss.common.utils.ValidUtils;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.net.SocketTimeoutException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.LifecycleOwner;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+import rxhttp.wrapper.exception.HttpStatusCodeException;
+import rxhttp.wrapper.param.RxHttp;
+import rxhttp.wrapper.param.RxHttpFormParam;
+import rxhttp.wrapper.param.RxHttpJsonParam;
+import rxhttp.wrapper.param.RxHttpNoBodyParam;
+
+
+/**
+ * Describe:网络请求帮助类
+ * Created by 吴天强 on 2020/1/3.
+ */
+@SuppressWarnings("unchecked")
+public class NetworkManage {
+ /**
+ * 取第一个进来的跳转到登录页
+ */
+ public volatile static int count = 0;
+ private static final String GET = "GET";
+ private static final String POST_FORM = "POST_FORM";
+ private static final String POST_JSON = "POST_JSON";
+ private static final String PUT_FORM = "PUT_FORM";
+ private static final String PUT_JSON = "PUT_JSON";
+ private static final String DELETE_FORM = "DELETE_FORM";
+ private static final String DELETE_JSON = "DELETE_JSON";
+ /**
+ * 账户相关的报错信息
+ */
+ private static final List ACCOUNT_ERROR_CODE = new ArrayList<>();
+
+ /**
+ * 无须加密白名单
+ */
+ private static final List NO_DECRYPTION_LIST = new ArrayList<>();
+
+ static {
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_DISABLE);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_QUIT);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_LOCKED);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_NO_AUTHORITY);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_NO_TEAM);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_MULTIPLE_TEAM);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_TOKEN_EXPIRED);
+ ACCOUNT_ERROR_CODE.add(Constants.Net.Status.CODE_ACCOUNT_POSITION_ERROR);
+
+ NO_DECRYPTION_LIST.add(Api.UPLOAD_FILE);
+ NO_DECRYPTION_LIST.add(Api.DOWNLOAD_FILE);
+ }
+
+ /**
+ * 构建Get请求
+ */
+ @NonNull
+ public static Request createGet() {
+ return create(GET);
+ }
+
+ /**
+ * 构建PostFrom请求
+ */
+ @NonNull
+ public static Request createPostForm() {
+ return create(POST_FORM);
+ }
+
+ /**
+ * 构建PostJson请求
+ */
+ @NonNull
+ public static Request createPostJson() {
+ return create(POST_JSON);
+ }
+
+ /**
+ * 构建PutForm请求
+ */
+ @NonNull
+ public static Request createPutForm() {
+ return create(PUT_FORM);
+ }
+
+ /**
+ * 构建PutJson请求
+ */
+ @NonNull
+ public static Request createPutJson() {
+ return create(PUT_JSON);
+ }
+
+ /**
+ * 构建DeleteForm请求
+ */
+ @NonNull
+ public static Request createDeleteForm() {
+ return create(DELETE_FORM);
+ }
+
+ /**
+ * 构建DeleteJson请求
+ */
+ @NonNull
+ public static Request createDeleteJson() {
+ return create(DELETE_JSON);
+ }
+
+
+ /**
+ * 构建请求类型
+ */
+ @Contract(value = "_ -> new", pure = true)
+ @NonNull
+ private static Request create(String method) {
+ return new Request(method);
+ }
+
+ /**
+ * 网络请求主类
+ */
+ public static class Request {
+ private String method;
+ private String requestId;
+
+
+ Request(String method) {
+ this.method = method;
+ requestId = UUID.randomUUID().toString().replaceAll("-", "");
+ }
+
+ /**
+ * 无参请求返回String类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ */
+ public Observable request(LifecycleOwner life, String url) {
+ return request(life, url, null, (Class) String.class);
+ }
+
+ /**
+ * 无参请求返回T类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ * @param type 响应泛型类型
+ */
+ public Observable request(LifecycleOwner life, String url, Class type) {
+ return request(life, url, null, type);
+ }
+
+ /**
+ * 有参请求返回String类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ * @param param 请求参数
+ */
+ public Observable request(LifecycleOwner life, String url, RequestParam param) {
+ return request(life, url, param, (Class) String.class);
+ }
+
+ /**
+ * 有参请求返回T类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URLu
+ * @param param 请求参数
+ * @param type 响应泛型类型
+ */
+ public Observable request(LifecycleOwner life, String url, RequestParam param, Class type) {
+ return Observable.create(
+ subscriber -> {
+ if (!NetworkUtil.isNetworkEnabled(BaseApplication.i())) {
+ //无可用网络
+ subscriber.onError(new NetErrorException(BaseApplication.i().getString(R.string.network_error_no_net)));
+ return;
+ }
+ Disposable subscribe = checkRequest(url, param)
+ .as(RxLife.asOnMain(life)) //感知生命周期,并在主线程回调
+ .subscribe(response ->
+ checkResponse(url, response).subscribe(baseResponse -> {
+ if (type == BaseResponse.class) {
+ subscriber.onNext((T) baseResponse);
+ } else if (type == String.class) {
+ subscriber.onNext((T) baseResponse.getData());
+ } else {
+ //根据类型解析
+ subscriber.onNext(JsonUtils.getObject(baseResponse.getData(), type));
+ }
+ }, subscriber::onError), throwable -> subscriber.onError(handleError(throwable)));
+ BaseApplication.i().addNetDisposable(requestId, subscribe);
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+ /**
+ * 无参请求返回List类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ * @param type 响应泛型类型
+ */
+ public Observable> requestList(LifecycleOwner life, String url, Class type) {
+ return requestList(life, url, null, type);
+ }
+
+ /**
+ * 有参请求返回List类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ * @param param 请求参数
+ */
+ public Observable> requestList(LifecycleOwner life, String url, RequestParam param) {
+ return requestList(life, url, param, (Class) String.class);
+ }
+
+ /**
+ * 有参请求返回List类型
+ *
+ * @param life 声明周期实现类
+ * @param url 请求URL
+ * @param param 请求参数
+ * @param type 响应泛型类型
+ */
+ public Observable> requestList(LifecycleOwner life, String url, RequestParam param, Class type) {
+ return Observable.>create(
+ subscriber -> {
+ if (!NetworkUtil.isNetworkEnabled(BaseApplication.i())) {
+ //无可用网络
+ subscriber.onError(new NetErrorException(BaseApplication.i().getString(R.string.network_error_no_net)));
+ return;
+ }
+ Disposable subscribe = checkRequest(url, param)
+ .as(RxLife.asOnMain(life)) //感知生命周期,并在主线程回调
+ .subscribe(response -> checkResponse(url, response).subscribe(
+ baseResponse -> subscriber.onNext(JsonUtils.getList(baseResponse.getData(), type)),
+ subscriber::onError), throwable -> subscriber.onError(handleError(throwable)));
+ BaseApplication.i().addNetDisposable(requestId, subscribe);
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+
+ /**
+ * 下载文件
+ *
+ * @param life 声明周期实现类
+ * @param downloadUrl 文件的下载地址
+ * @param localPath 本地保存的文件路径
+ * @return 下载response
+ */
+ public Observable requestDownload(LifecycleOwner life, String downloadUrl, String localPath) {
+ return Observable.create(
+ subscriber -> {
+ if (!NetworkUtil.isNetworkEnabled(BaseApplication.i())) {
+ //无可用网络
+ subscriber.onError(new NetErrorException(BaseApplication.i().getString(R.string.network_error_no_net)));
+ return;
+ }
+ Logger.e("文件下载地址:" + downloadUrl);
+ DownloadResponse downloadResponse = new DownloadResponse();
+ //下载失败,处理相关逻辑
+ RxHttp.get(downloadUrl)
+ .asDownload(localPath, progress -> {
+ Logger.i("文件下载中," + progress);
+ //下载进度回调,0-100,仅在进度有更新时才会回调,最多回调101次,最后一次回调文件存储路径
+ downloadResponse.setProgress(progress);
+ subscriber.onNext(downloadResponse);
+ })
+ .observeOn(AndroidSchedulers.mainThread())
+ .as(RxLife.as(life))
+ .subscribe(s -> {
+ Logger.e("文件下载完成,保存:" + s);
+ //下载完成,处理相关逻辑
+ downloadResponse.setSuccess(true);
+ subscriber.onNext(downloadResponse);
+ }, subscriber::onError);
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+
+ /**
+ * 检查响应
+ *
+ * @param apiUrl 接口地址
+ * @param response 响应数据
+ * @return BaseResponse
+ */
+ private Observable checkResponse(String apiUrl, String response) {
+ return Observable.create(subscriber -> {
+ BaseApplication.i().removeNetDisposable(requestId);
+ Logger.e(String.format("Request-Id:%s\n响应:%s", requestId, response));
+ String state = JsonUtils.getString(response, Constants.Net.STATE);
+ String message = JsonUtils.getString(response, Constants.Net.MESSAGE);
+ String data;
+ try {
+ //防止返回的data为null导致解析json失败
+ data = JsonUtils.getString(response, Constants.Net.DATA);
+ } catch (Exception e) {
+ data = "";
+ }
+ if (Constants.Net.Status.CODE_SUCCESS.equals(state)) {
+ subscriber.onNext(new BaseResponse(state, message, data));
+ } else {
+ if (!Api.LOGIN.equals(apiUrl) && ACCOUNT_ERROR_CODE.contains(state)) {
+ //如果是非登录接口且错误码为定义的这部分,则需要跳转到登录页面
+ synchronized (NetworkManage.class) {
+ //防止多个线程一瞬间进来了,让需要进来的进行排队
+ if (count <= 0) {
+ //Token 过期 跳转登录页面
+ toLoginActivity(message);
+ }
+ count++;
+ }
+ } else {
+ //接口返回 false 把message、data扔出去
+ subscriber.onError(new NetErrorException(state, message, data));
+ }
+ }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+
+ /**
+ * 网络请求之前参数检查,组装公共请求参数,加密等操作
+ *
+ * @param url 接口地址
+ * @param param 请求参数
+ * @return Observable
+ */
+ @NotNull
+ private Observable checkRequest(String url, RequestParam param) {
+ if (!ValidUtils.isValid(param)) {
+ param = new RequestParam();
+ }
+ //打印请求
+ Logger.e(String.format("Request-Id:%s\n%s %s%s\n请求参数:%s", requestId, method, Api.BASE_URL, url, JsonUtils.toJson(param.getParameter())));
+ RxHttp rxHttp = buildRequest(url, param);
+ //添加Header
+ for (Map.Entry entry : buildHeader().entrySet()) {
+ rxHttp.addHeader(entry.getKey(), entry.getValue());
+ }
+ return rxHttp.asString();
+ }
+
+ /**
+ * 构建请求
+ *
+ * @param url 接口地址
+ * @param param 请求参数
+ * @return RxHttp
+ */
+ private RxHttp buildRequest(String url, @NotNull RequestParam param) {
+ Map fileMap = new HashMap<>(16);
+ Map> fileListMap = new HashMap<>(16);
+ Map objectMap = new HashMap<>(16);
+
+ //分离请求参数中的文件
+ for (Map.Entry entry : param.getParameter().entrySet()) {
+ if (entry.getValue() instanceof File) {
+ //单个文件
+ fileMap.put(entry.getKey(), (File) entry.getValue());
+ continue;
+ }
+ if (entry.getValue() instanceof List && ((List) entry.getValue()).size() > 0) {
+ if (((List) entry.getValue()).get(0) instanceof File) {
+ //文件list
+ fileListMap.put(entry.getKey(), (List) entry.getValue());
+ continue;
+ }
+ }
+
+ if (entry.getValue() instanceof String) {
+ //把null转成""
+ String value = String.valueOf(entry.getValue());
+ if (!ValidUtils.isValid(value) || "null".equalsIgnoreCase(value)) {
+ value = "";
+ }
+ objectMap.put(entry.getKey(), value);
+ continue;
+ }
+ objectMap.put(entry.getKey(), entry.getValue());
+ }
+
+ Map requestParam = new HashMap<>();
+ String paramJson = JsonUtils.toJson(objectMap);
+ /*
+ *注:该加密方式为:把请求参数key、value以json的格式整体加密,然后再以key、value的形式发送给服务器
+ */
+ if (!NO_DECRYPTION_LIST.contains(url) && ProfileManager.profile().isSecret()) {
+ //请求是否需要加密
+ requestParam.put(Constants.Net.REQUEST_DATA, AesUtils.getInstance().encrypt(paramJson));
+ } else {
+ requestParam.put(Constants.Net.REQUEST_DATA, paramJson);
+ }
+ Logger.i(String.format("加密请求\nRequest-Id:%s\n%s %s%s\n请求参数:%s",
+ requestId, method, Api.BASE_URL, url, JsonUtils.toJson(requestParam)));
+ RxHttp rxHttp;
+ switch (method) {
+ case POST_JSON:
+ case PUT_JSON:
+ case DELETE_JSON:
+ //JSON格式请求
+ if (TextUtils.equals(method, POST_JSON)) {
+ rxHttp = RxHttp.postJson(url);
+ } else if (TextUtils.equals(method, DELETE_JSON)) {
+ rxHttp = RxHttp.deleteJson(url);
+ } else {
+ rxHttp = RxHttp.putJson(url);
+ }
+ if (isUpLoadFile(url)) {
+ //上传文件传参特殊
+ ((RxHttpJsonParam) rxHttp).addAll(objectMap);
+ } else {
+ ((RxHttpJsonParam) rxHttp).addAll(requestParam);
+ }
+
+ //添加文件请求参数
+ if (!fileMap.isEmpty()) {
+ for (Map.Entry entry : fileMap.entrySet()) {
+ ((RxHttpJsonParam) rxHttp).add(entry.getKey(), entry.getValue());
+ }
+ }
+ if (!fileListMap.isEmpty()) {
+ for (Map.Entry> entry : fileListMap.entrySet()) {
+ ((RxHttpJsonParam) rxHttp).add(entry.getKey(), entry.getValue());
+ }
+ }
+ break;
+ case POST_FORM:
+ case PUT_FORM:
+ case DELETE_FORM:
+ //POST格式请求
+ if (TextUtils.equals(method, POST_FORM)) {
+ rxHttp = RxHttp.postForm(url);
+ } else if (TextUtils.equals(method, DELETE_FORM)) {
+ rxHttp = RxHttp.deleteForm(url);
+ } else {
+ rxHttp = RxHttp.putForm(url);
+ }
+ if (isUpLoadFile(url)) {
+ //上传文件传参特殊
+ ((RxHttpFormParam) rxHttp).addAll(objectMap);
+ } else {
+ ((RxHttpFormParam) rxHttp).addAll(requestParam);
+ }//添加文件请求参数
+ if (!fileMap.isEmpty()) {
+ for (Map.Entry entry : fileMap.entrySet()) {
+ ((RxHttpFormParam) rxHttp).addFile(entry.getKey(), entry.getValue());
+ }
+ }
+ if (!fileListMap.isEmpty()) {
+ for (Map.Entry> entry : fileListMap.entrySet()) {
+ ((RxHttpFormParam) rxHttp).addFile(entry.getKey(), entry.getValue());
+ }
+ }
+ break;
+ case GET:
+ default:
+ rxHttp = RxHttp.get(url);
+ ((RxHttpNoBodyParam) rxHttp).addAll(requestParam);
+ //添加文件请求参数
+ if (!fileMap.isEmpty()) {
+ for (Map.Entry entry : fileMap.entrySet()) {
+ ((RxHttpNoBodyParam) rxHttp).add(entry.getKey(), entry.getValue());
+ }
+ }
+ if (!fileListMap.isEmpty()) {
+ for (Map.Entry> entry : fileListMap.entrySet()) {
+ ((RxHttpNoBodyParam) rxHttp).add(entry.getKey(), entry.getValue());
+ }
+ }
+ break;
+ }
+ return rxHttp;
+ }
+
+ /**
+ * 构建请求头
+ *
+ * @return 请求头Map
+ */
+ @NotNull
+ private Map buildHeader() {
+ String deviceId = BaseApplication.i().getDeviceId();
+ String token = BaseApplication.i().getLoginToken();
+ Map header = new HashMap<>();
+ header.put(Constants.Net.HEADER_CHANNEL, Constants.Common.CHANEL);
+ header.put(Constants.Net.HEADER_API_VERSION, Constants.Common.API_VERSION);
+ header.put(Constants.Net.HEADER_DEVICE_ID, ValidUtils.isValid(deviceId) ? deviceId : "");
+ header.put(Constants.Net.HEADER_TOKEN, ValidUtils.isValid(token) ? token : "");
+ header.put(Constants.Net.HEADER_APP_VERSION, Utils.getVersionName());
+ header.put(Constants.Net.HEADER_IP, NetworkUtil.getIpAddress());
+ header.put(Constants.Net.REQUEST_ID, requestId);
+ Logger.i("请求Header:\n" + JsonUtils.toJson(header));
+ return header;
+ }
+
+ /**
+ * 检查是否上传文件
+ *
+ * @param url url
+ * @return boolean
+ */
+ @Contract(value = "null -> false", pure = true)
+ private boolean isUpLoadFile(String url) {
+ return Api.UPLOAD_FILE.equals(url);
+ }
+
+
+ /**
+ * 处理网络请求中的异常
+ *
+ * @param t Throwable
+ * @return NetErrorException
+ */
+ @Contract("_ -> new")
+ @NotNull
+ private NetErrorException handleError(@NotNull Throwable t) {
+ BaseApplication.i().removeNetDisposable(requestId);
+ String errorMessage = null;
+ String loggerMessage = "";
+ if (t instanceof SocketTimeoutException) {
+ errorMessage = BaseApplication.i().getString(R.string.request_time_out);
+ loggerMessage = errorMessage;
+ } else if (t instanceof HttpStatusCodeException) {
+ HttpStatusCodeException codeException = (HttpStatusCodeException) t;
+ try {
+ errorMessage = JsonUtils.getString(codeException.getResult(), Constants.Net.MESSAGE);
+ } catch (Exception e) {
+ errorMessage = BaseApplication.i().getString(R.string.network_error_server_error);
+ }
+ loggerMessage = String.format("%s %s", codeException.getStatusCode(), errorMessage);
+ } else {
+ loggerMessage = t.getMessage();
+ }
+ if (!ValidUtils.isValid(errorMessage)) {
+ errorMessage = BaseApplication.i().getString(R.string.network_error_server_error);
+ }
+ Logger.e(String.format("Request-Id:%s\n请求报错:%s", requestId, loggerMessage));
+ return new NetErrorException(errorMessage);
+ }
+
+ /**
+ * 跳转登录页
+ *
+ * @param errorMessage 错误信息
+ */
+ private void toLoginActivity(String errorMessage) {
+ Observable.create(
+ subscriber -> {
+ //检查是否存在未完成的请求,有就取消
+ for (Map.Entry entry : BaseApplication.i().getNetDisposables().entrySet()) {
+ if (!entry.getValue().isDisposed()) {
+ entry.getValue().dispose();
+ }
+ }
+ ToastUtils.show(errorMessage);
+ //延时1秒跳转到登录页,最大限度的,避免由于网络延时,带来的token过期退出到登录页的异常
+ new Handler().postDelayed(() -> {
+ ActivityToActivity.toLoginActivity(BaseApplication.i());
+ BaseApplication.i().loginOutClean();
+ }, 500);
+
+ })
+ .subscribeOn(AndroidSchedulers.mainThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe();
+ }
+
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/net/RequestParam.java b/common_base/src/main/java/com/wss/common/net/RequestParam.java
deleted file mode 100644
index 6f2bf06..0000000
--- a/common_base/src/main/java/com/wss/common/net/RequestParam.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.wss.common.net;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-
-/**
- * Describe:请求参数封装类
- * Created by 吴天强 on 2017/9/19.
- */
-public class RequestParam {
-
- private Map params;
-
- public RequestParam() {
- params = new LinkedHashMap<>();
- }
-
- /**
- * 普通文本参数
- *
- * @param key key
- * @param value 值
- */
- public void addParameter(String key, Object value) {
- if (this.params == null) {
- params = new LinkedHashMap<>();
- }
- params.put(key, value);
- }
-
-
- public void addParameter(String key, int value) {
- addParameter(key, String.valueOf(value));
- }
-
- public void addParameter(String key, long value) {
- addParameter(key, String.valueOf(value));
- }
-
- public void addParameter(String key, float value) {
- addParameter(key, String.valueOf(value));
- }
-
- public void addParameter(String key, double value) {
- addParameter(key, String.valueOf(value));
- }
-
- /**
- * 获取请求参数
- *
- * @return Map
- */
- public Map getParameter() {
- if (null == params) {
- params = new LinkedHashMap<>();
- }
- return params;
- }
-
-
- /**
- * 请求参数转Json
- *
- * @return String
- */
- String toJson() {
- JSONObject json = new JSONObject();
- for (Map.Entry entry : params.entrySet()) {
- try {
- json.put(entry.getKey(), entry.getValue());
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- return json.toString();
- }
-
- @Override
- public String toString() {
- StringBuilder stringBuffer = new StringBuilder();
- for (Map.Entry entry : params.entrySet()) {
- stringBuffer.append(entry.getKey());
- stringBuffer.append(":");
- stringBuffer.append(entry.getValue());
- stringBuffer.append("\t");
- }
- return stringBuffer.toString();
- }
-
-}
diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java
deleted file mode 100644
index 468b6a4..0000000
--- a/common_base/src/main/java/com/wss/common/net/callback/OnResultCallBack.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.wss.common.net.callback;
-
-
-import com.tamic.novate.Throwable;
-import com.tamic.novate.callback.RxGenericsCallback;
-
-import java.io.IOException;
-
-import okhttp3.Call;
-import okhttp3.ResponseBody;
-
-/**
- * Describe:网络返回基类
- * Created by 吴天强 on 2017/9/26.
- */
-
-public abstract class OnResultCallBack extends RxGenericsCallback {
- protected boolean success;
-
- @Override
- public void onError(Object tag, Throwable e) {
- e.printStackTrace();
- onFailure(tag, e);
- }
-
-
- @Override
- public void onCancel(Object tag, Throwable e) {
- }
-
- @Override
- public void onFailure(Call call, IOException e) {
- onFailure(tag, e);
- }
-
- @Override
- public void onNext(Object tag, int code, String message, T response) {
- onSuccess(success, code, msg, tag, response);
- }
-
- @Override
- public void onCompleted(Object tag) {
- super.onCompleted(tag);
- onCompleted();
- }
-
- public abstract void onSuccess(boolean success, int code, String msg, Object tag, T response);
-
- public abstract void onFailure(Object tag, Exception e);
-
- public abstract void onCompleted();
-
-
-}
diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java
deleted file mode 100644
index a113abb..0000000
--- a/common_base/src/main/java/com/wss/common/net/callback/OnResultListCallBack.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.wss.common.net.callback;
-
-import com.alibaba.fastjson.JSON;
-import com.google.gson.Gson;
-import com.orhanobut.logger.Logger;
-import com.wss.common.net.NetConfig;
-
-import org.json.JSONObject;
-
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
-import okhttp3.ResponseBody;
-
-/**
- * Describe:返回数组类型数据
- * Created by 吴天强 on 2017/9/28.
- */
-
-public abstract class OnResultListCallBack extends OnResultCallBack {
-
- private Type collectionType;
-
- @Override
- public T onHandleResponse(ResponseBody response) throws Exception {
- if (collectionType == null) {
- collectionType = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
- }
- return transform(new String(response.bytes()), null);
- }
-
- public T transform(String response, final Class classOfT) throws ClassCastException {
- Logger.e(JSON.toJSONString(response));
- try {
- JSONObject jsonObject = new JSONObject(response);
- code = jsonObject.optInt(NetConfig.Code.CODE);
- msg = jsonObject.optString(NetConfig.Code.MSG);
- success = jsonObject.optBoolean(NetConfig.Code.SUCCESS);
- dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString();
- dataResponse = new Gson().fromJson(dataStr, collectionType);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return dataResponse;
- }
-}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java
deleted file mode 100644
index 151c250..0000000
--- a/common_base/src/main/java/com/wss/common/net/callback/OnResultObjectCallBack.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.wss.common.net.callback;
-
-import com.google.gson.Gson;
-import com.orhanobut.logger.Logger;
-import com.wss.common.net.NetConfig;
-
-import org.json.JSONObject;
-
-import java.lang.reflect.ParameterizedType;
-
-import okhttp3.ResponseBody;
-
-/**
- * Describe:返回对象类型数据
- * Created by 吴天强 on 2017/9/28.
- */
-
-public abstract class OnResultObjectCallBack extends OnResultCallBack {
-
- @Override
- public T onHandleResponse(ResponseBody response) throws Exception {
- Class entityClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
- return transform(new String(response.bytes()), entityClass);
- }
-
- public T transform(String response, final Class classOfT) throws ClassCastException {
- Logger.e(response);
- try {
- JSONObject jsonObject = new JSONObject(response);
-
- code = jsonObject.optInt(NetConfig.Code.CODE);
- msg = jsonObject.optString(NetConfig.Code.MSG);
- success = jsonObject.optBoolean(NetConfig.Code.SUCCESS);
- dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString();
- dataResponse = (T) new Gson().fromJson(dataStr, classOfT);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return dataResponse;
- }
-}
-
diff --git a/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java b/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java
deleted file mode 100644
index eec4ce6..0000000
--- a/common_base/src/main/java/com/wss/common/net/callback/OnResultStringCallBack.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.wss.common.net.callback;
-
-import com.alibaba.fastjson.JSON;
-import com.orhanobut.logger.Logger;
-import com.wss.common.net.NetConfig;
-
-import org.json.JSONObject;
-
-import okhttp3.ResponseBody;
-
-/**
- * Describe:String类型数据解析
- * Created by 吴天强 on 2017/9/28.
- */
-
-public abstract class OnResultStringCallBack extends OnResultCallBack {
-
- @Override
- public String onHandleResponse(ResponseBody response) throws Exception {
- return transform(new String(response.bytes()));
- }
-
- private String transform(String response) {
- Logger.e(JSON.toJSONString(response));
- try {
- JSONObject jsonObject = new JSONObject(response);
- code = jsonObject.optInt(NetConfig.Code.CODE);
- msg = jsonObject.optString(NetConfig.Code.MSG);
- success = jsonObject.optBoolean(NetConfig.Code.SUCCESS);
- dataStr = jsonObject.opt(NetConfig.Code.MODEL).toString();
- dataResponse = dataStr;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return dataResponse;
- }
-
-}
diff --git a/common_base/src/main/java/com/wss/common/net/request/RequestParam.java b/common_base/src/main/java/com/wss/common/net/request/RequestParam.java
new file mode 100644
index 0000000..5d0e5b4
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/net/request/RequestParam.java
@@ -0,0 +1,133 @@
+package com.wss.common.net.request;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+
+/**
+ * Describe:请求参数封装类
+ * Created by 吴天强 on 2017/9/19.
+ */
+public class RequestParam {
+
+ /**
+ * 存放请求参数的Map
+ */
+ private Map params;
+
+ public RequestParam() {
+ params = new LinkedHashMap<>();
+ }
+
+ /**
+ * 添加请求参数
+ *
+ * @param key key
+ * @param value 值
+ */
+ private void buildParameter(String key, Object value) {
+ if (this.params == null) {
+ params = new LinkedHashMap<>();
+ }
+ params.put(key, value);
+ }
+
+ /**
+ * 添加普通文本
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, String value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加int类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Integer value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加long类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Long value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加float类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Float value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加double类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Double value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加boolean类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Boolean value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 添加Object类型
+ *
+ * @param key key
+ * @param value 值
+ */
+ public void addParameter(String key, Object value) {
+ buildParameter(key, value);
+ }
+
+ /**
+ * 获取请求参数
+ *
+ * @return Map
+ */
+ public Map getParameter() {
+ if (null == params) {
+ params = new LinkedHashMap<>();
+ }
+ return params;
+ }
+
+
+ @NotNull
+ @Override
+ public String toString() {
+ StringBuilder stringBuffer = new StringBuilder();
+ for (Map.Entry entry : params.entrySet()) {
+ stringBuffer.append(entry.getKey());
+ stringBuffer.append(":");
+ stringBuffer.append(entry.getValue());
+ stringBuffer.append("\t");
+ }
+ return stringBuffer.toString();
+ }
+
+}
diff --git a/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java b/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java
new file mode 100644
index 0000000..08f2acd
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/net/response/BaseResponse.java
@@ -0,0 +1,34 @@
+package com.wss.common.net.response;
+
+
+import com.wss.common.base.bean.BaseBean;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Describe:响应基类
+ * Created by 吴天强 on 2020/5/6.
+ */
+@Getter
+@Setter
+public class BaseResponse extends BaseBean {
+ /**
+ * 响应码
+ */
+ private String code;
+ /**
+ * 响应message
+ */
+ private String msg;
+ /**
+ * 响应数据
+ */
+ private String data;
+
+ public BaseResponse(String code, String msg, String data) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/net/response/DownloadResponse.java b/common_base/src/main/java/com/wss/common/net/response/DownloadResponse.java
new file mode 100644
index 0000000..2ad97dc
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/net/response/DownloadResponse.java
@@ -0,0 +1,25 @@
+package com.wss.common.net.response;
+
+
+import com.wss.common.base.bean.BaseBean;
+
+import lombok.Getter;
+import lombok.Setter;
+import rxhttp.wrapper.entity.Progress;
+
+/**
+ * Describe:下载文件响应
+ * Created by 吴天强 on 2021/5/10.
+ */
+@Getter
+@Setter
+public class DownloadResponse extends BaseBean {
+ /**
+ * 下载文件进度对象
+ */
+ private Progress progress;
+ /**
+ * 是否下载完成
+ */
+ private boolean success;
+}
diff --git a/common_base/src/main/java/com/wss/common/profile/IProfile.java b/common_base/src/main/java/com/wss/common/profile/IProfile.java
new file mode 100644
index 0000000..4e9839d
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/profile/IProfile.java
@@ -0,0 +1,31 @@
+package com.wss.common.profile;
+
+/**
+ * Describe:编译环境相关的配置
+ * 该类定义 由APP模块的具体实现类创建不同环境的配置
+ * Created by 吴天强 on 2019/5/23.
+ */
+public interface IProfile {
+
+ /**
+ * 服务地址
+ *
+ * @return API地址
+ */
+ String getServiceBase();
+
+ /**
+ * 请求是否加密
+ *
+ * @return boolean
+ */
+ boolean isSecret();
+
+ /**
+ * 返回Aes加解密key
+ *
+ * @return key
+ */
+ String getAesSecretKey();
+
+}
diff --git a/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java b/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java
new file mode 100644
index 0000000..af8a080
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/profile/IProfileFactory.java
@@ -0,0 +1,15 @@
+package com.wss.common.profile;
+
+/**
+ * Describe:环境配置工厂接口
+ * Created by 吴天强 on 2019/5/23.
+ */
+public interface IProfileFactory {
+
+ /**
+ * 创建配置文件
+ *
+ * @return 配置文件
+ */
+ IProfile createProfile();
+}
diff --git a/common_base/src/main/java/com/wss/common/profile/ProfileManager.java b/common_base/src/main/java/com/wss/common/profile/ProfileManager.java
new file mode 100644
index 0000000..65895bb
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/profile/ProfileManager.java
@@ -0,0 +1,41 @@
+package com.wss.common.profile;
+
+/**
+ * Describe:编译环境相关的配置 管理类
+ * Created by 吴天强 on 2019/5/23.
+ */
+public class ProfileManager {
+
+ private IProfileFactory mFactory;
+ private IProfile mProfile;
+ public static final ProfileManager inst;
+
+ public void factory(IProfileFactory factory) {
+ this.mFactory = factory;
+ }
+
+ public static IProfile profile() {
+ return inst.getProfile();
+ }
+
+ private IProfile getProfile() {
+ if (this.mProfile == null) {
+ this.mProfile = this.mFactory.createProfile();
+ }
+ return this.mProfile;
+ }
+
+ private ProfileManager() {
+ }
+
+ static {
+ inst = Holder.holder;
+ }
+
+ private static final class Holder {
+ private static final ProfileManager holder = new ProfileManager();
+
+ private Holder() {
+ }
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/secret/AesUtils.java b/common_base/src/main/java/com/wss/common/secret/AesUtils.java
new file mode 100644
index 0000000..bad264b
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/secret/AesUtils.java
@@ -0,0 +1,104 @@
+package com.wss.common.secret;//package com.xincheng.common.secret;
+
+
+import com.wss.common.profile.ProfileManager;
+
+import org.bouncycastle.util.encoders.Base64;
+
+import java.net.URLEncoder;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+
+/**
+ * Describe:AES 加解密操作
+ * Created by 吴天强 on 2018-08-03 17:47
+ **/
+public class AesUtils {
+
+ private static final String ALGORITHM = "AES/ECB/PKCS5Padding";
+ private static final String KEY = ProfileManager.profile().getAesSecretKey();
+
+ private static AesUtils aesUtils;
+
+ private AesUtils() {
+ }
+
+ public static AesUtils getInstance() {
+ if (aesUtils == null) {
+ synchronized (AesUtils.class) {
+ if (aesUtils == null) {
+ aesUtils = new AesUtils();
+ }
+ }
+ }
+ return aesUtils;
+ }
+
+ /**
+ * 获取秘钥方法
+ */
+ private byte[] getKey() {
+ KeyGenerator kg;
+ try {
+ kg = KeyGenerator.getInstance("AES");
+ kg.init(192);
+ SecretKey sk = kg.generateKey();
+ byte[] b = sk.getEncoded();
+ System.out.println("KEY---------" + new String(Base64.encode(b)));
+ return b;
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * AES加密方法
+ *
+ * @param str 需要加密的字符串
+ * @return 加密后数据
+ */
+ public String encrypt(String str) {
+ byte[] result;
+ try {
+ Cipher cipher = Cipher.getInstance(ALGORITHM);
+ //生成加密解密需要的Key
+ SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(KEY.getBytes()), "AES");
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec);
+ result = cipher.doFinal(str.getBytes("UTF-8"));
+ return URLEncoder.encode(new String(Base64.encode(result)), "UTF-8");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+ /**
+ * AES解密方法
+ *
+ * @param str 需要加密的字符串
+ * @return 解密后数据
+ */
+ public String decrypt(String str) {
+ String result = null;
+ try {
+ Cipher cipher = Cipher.getInstance(ALGORITHM);
+ SecretKeySpec keySpec = new SecretKeySpec(Base64.decode(KEY.getBytes()), "AES");
+ cipher.init(Cipher.DECRYPT_MODE, keySpec);
+ byte[] decoded = cipher.doFinal(Base64.decode(str.getBytes()));
+ result = new String(decoded, "UTF-8");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+}
+
+
diff --git a/common_base/src/main/java/com/wss/common/secret/MD5.java b/common_base/src/main/java/com/wss/common/secret/MD5.java
new file mode 100644
index 0000000..e8e9abf
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/secret/MD5.java
@@ -0,0 +1,64 @@
+package com.wss.common.secret;
+
+
+import org.jetbrains.annotations.NotNull;
+
+import java.security.MessageDigest;
+
+/**
+ * Describe:MD5加密
+ * Created by 吴天强 on 2017/10/9.
+ */
+public class MD5 {
+ /**
+ * 生成md5
+ *
+ * @param message 加密字段
+ * @return String
+ */
+ @NotNull
+ public static String getMD5(String message) {
+ String md5str = "";
+ try {
+ // 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ // 2 将消息变成byte数组
+ byte[] input = message.getBytes();
+ // 3 计算后获得字节数组,这就是那128位了
+ byte[] buff = md.digest(input);
+ // 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串
+ md5str = bytesToHex(buff);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return md5str.toLowerCase();
+ }
+
+ /**
+ * 二进制转十六进制
+ *
+ * @param bytes bytes
+ * @return String
+ */
+ @NotNull
+ private static String bytesToHex(@NotNull byte[] bytes) {
+ StringBuilder md5str = new StringBuilder();
+ // 把数组每一字节换成16进制连成md5字符串
+ int digital;
+ for (byte aByte : bytes) {
+ digital = aByte;
+
+ if (digital < 0) {
+ digital += 256;
+ }
+ if (digital < 16) {
+ md5str.append("0");
+ }
+ md5str.append(Integer.toHexString(digital));
+ }
+ return md5str.toString().toUpperCase();
+ }
+
+
+}
diff --git a/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java b/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java
new file mode 100644
index 0000000..bfc5d44
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/secret/ParseSystemUtil.java
@@ -0,0 +1,50 @@
+package com.wss.common.secret;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Describe:16进制与二进制转换类
+ * Created by 吴天强 on 2018-08-03 16:31
+ **/
+public class ParseSystemUtil {
+ /**
+ * 将二进制转换成16进制
+ *
+ * @param buf 数据
+ * @return String
+ */
+ @NotNull
+ public static String parseByte2HexStr(@NotNull byte[] buf) {
+ StringBuilder sb = new StringBuilder();
+ for (byte b : buf) {
+ String hex = Integer.toHexString(b & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ sb.append(hex.toUpperCase());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 将16进制转换为二进制
+ *
+ * @param hexStr 数据
+ * @return byte[]
+ */
+ @Nullable
+ public static byte[] parseHexStr2Byte(@NotNull String hexStr) {
+ if (hexStr.length() < 1)
+ return null;
+ byte[] result = new byte[hexStr.length() / 2];
+ for (int i = 0; i < hexStr.length() / 2; i++) {
+ int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
+ int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
+ result[i] = (byte) (high * 16 + low);
+ }
+ return result;
+ }
+}
+
+
diff --git a/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java b/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java
new file mode 100644
index 0000000..ff5eebb
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/ARouterUtils.java
@@ -0,0 +1,36 @@
+package com.wss.common.utils;
+
+import com.alibaba.android.arouter.launcher.ARouter;
+import com.wss.common.base.BaseActivity;
+import com.wss.common.base.BaseFragment;
+
+/**
+ * Describe:ARouter帮助类
+ * Created by 吴天强 on 2018/11/13.
+ */
+public class ARouterUtils {
+
+ /**
+ * 根据path返回Fragment
+ *
+ * @param path path
+ * @return fragment
+ */
+ public static BaseFragment getFragment(String path) {
+ return (BaseFragment) ARouter.getInstance()
+ .build(path)
+ .navigation();
+ }
+
+ /**
+ * 根据path返回Activity
+ *
+ * @param path path
+ * @return Activity
+ */
+ public static BaseActivity getActivity(String path) {
+ return (BaseActivity) ARouter.getInstance()
+ .build(path)
+ .navigation();
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java b/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java
deleted file mode 100644
index dc8a074..0000000
--- a/common_base/src/main/java/com/wss/common/utils/ActivityToActivity.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.wss.common.utils;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-
-import com.wss.common.base.bean.BaseBean;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Describe:Activity跳转
- * Created by 吴天强 on 2018/10/22.
- */
-
-public class ActivityToActivity {
-
-
- public static void toActivity(Context activity, Class extends Activity> clazz) {
- toActivity(activity, clazz, null);
- }
-
- public static void toActivity(Context activity, Class extends Activity> clazz,
- Map params) {
- Intent intent = new Intent(activity, clazz);
- if (params != null) {
- for (Map.Entry entry : params.entrySet()) {
- String key = entry.getKey();
- Object value = params.get(key);
- if (value instanceof String) {
- intent.putExtra(key, (String) value);
- } else if (value instanceof Boolean) {
- intent.putExtra(key, (boolean) value);
- } else if (value instanceof Integer) {
- intent.putExtra(key, (int) value);
- } else if (value instanceof Float) {
- intent.putExtra(key, (float) value);
- } else if (value instanceof Double) {
- intent.putExtra(key, (double) value);
- } else if (value instanceof Long) {
- intent.putExtra(key, (long) value);
- } else if (value instanceof Short) {
- intent.putExtra(key, (short) value);
- } else if (value instanceof BaseBean) {
- intent.putExtra(key, (BaseBean) value);
- } else if (value instanceof ArrayList) {
- intent.putExtra(key, (ArrayList) value);
- } else if (value instanceof HashMap) {
- intent.putExtra(key, (HashMap) value);
- }
- }
- }
- activity.startActivity(intent);
- }
-
-
-}
diff --git a/common_base/src/main/java/com/wss/common/utils/BasicThreadFactory.java b/common_base/src/main/java/com/wss/common/utils/BasicThreadFactory.java
new file mode 100644
index 0000000..0c0302b
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/BasicThreadFactory.java
@@ -0,0 +1,14 @@
+package com.wss.common.utils;
+
+import java.util.concurrent.ThreadFactory;
+
+/**
+ * Describe:
+ * Created by 吴天强 on 2020/8/27.
+ */
+public class BasicThreadFactory implements ThreadFactory {
+ @Override
+ public Thread newThread(Runnable r) {
+ return null;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java b/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java
new file mode 100644
index 0000000..7cbaf2f
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/BeanCopyUtils.java
@@ -0,0 +1,48 @@
+package com.wss.common.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Describe:实体类Copy
+ * Created by 吴天强 on 2018/11/5.
+ */
+public class BeanCopyUtils {
+
+ @SuppressWarnings("unchecked")
+ public static T copy(T src) {
+ ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
+ ObjectOutputStream out = null;
+ ObjectInputStream in = null;
+ T dist = null;
+ try {
+ out = new ObjectOutputStream(memoryBuffer);
+ out.writeObject(src);
+ out.flush();
+ in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
+ dist = (T) in.readObject();
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ if (out != null)
+ try {
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ if (in != null)
+ try {
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return dist;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/utils/CacheUtils.java b/common_base/src/main/java/com/wss/common/utils/CacheUtils.java
index 426841e..bfe02b3 100644
--- a/common_base/src/main/java/com/wss/common/utils/CacheUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/CacheUtils.java
@@ -8,6 +8,9 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -40,35 +43,40 @@
* Describe:缓存工具类。。。能缓存普通的字符串、JsonObject、JsonArray、 Bitmap、Drawable、序列化的java对象,和 byte数据。
* Created by 吴天强 on 2017/10/9.
*/
-
public class CacheUtils {
- public static final int TIME_MINUTE = 60;
- public static final int TIME_HOUR = 60 * 60;
- public static final int TIME_DAY = TIME_HOUR * 24;
+ private static final int TIME_MINUTE = 60;
+ private static final int TIME_HOUR = 60 * TIME_MINUTE;
+ private static final int TIME_DAY = TIME_HOUR * 24;
+ private static final int MAX_TIME_OUT = 90 * TIME_DAY;//最大缓存90天
private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb
private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量
private static Map mInstanceMap = new HashMap<>();
private ACacheManager mCache;
+ @NotNull
public static CacheUtils get(Context ctx) {
return get(ctx, CacheUtils.class.getSimpleName());
}
- public static CacheUtils get(Context ctx, String cacheName) {
+ @NotNull
+ public static CacheUtils get(@NotNull Context ctx, String cacheName) {
File f = new File(ctx.getCacheDir(), cacheName);
return get(f, MAX_SIZE, MAX_COUNT);
}
+ @NotNull
public static CacheUtils get(File cacheDir) {
return get(cacheDir, MAX_SIZE, MAX_COUNT);
}
- public static CacheUtils get(Context ctx, long max_zise, int max_count) {
+ @NotNull
+ public static CacheUtils get(@NotNull Context ctx, long max_zise, int max_count) {
File f = new File(ctx.getCacheDir(), CacheUtils.class.getSimpleName());
return get(f, max_zise, max_count);
}
- public static CacheUtils get(File cacheDir, long max_zise, int max_count) {
+ @NotNull
+ public static CacheUtils get(@NotNull File cacheDir, long max_zise, int max_count) {
CacheUtils manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid());
if (manager == null) {
manager = new CacheUtils(cacheDir, max_zise, max_count);
@@ -77,11 +85,12 @@ public static CacheUtils get(File cacheDir, long max_zise, int max_count) {
return manager;
}
+ @NotNull
private static String myPid() {
return "_" + android.os.Process.myPid();
}
- private CacheUtils(File cacheDir, long max_size, int max_count) {
+ private CacheUtils(@NotNull File cacheDir, long max_size, int max_count) {
if (!cacheDir.exists() && !cacheDir.mkdirs()) {
throw new RuntimeException("can't make dirs in "
+ cacheDir.getAbsolutePath());
@@ -117,6 +126,16 @@ public void close() throws IOException {
// ============ String数据 读写 ==============
// =======================================
+ /**
+ * 保存 String数据 到 缓存中
+ *
+ * @param key 保存的key
+ * @param value 保存的String数据
+ */
+ public void put(String key, boolean value) {
+ put(key, String.valueOf(value));
+ }
+
/**
* 保存 String数据 到 缓存中
*
@@ -124,11 +143,23 @@ public void close() throws IOException {
* @param value 保存的String数据
*/
public void put(String key, String value) {
+ put(key, value, MAX_TIME_OUT);
+ }
+
+ /**
+ * 保存 String数据 到 缓存中
+ *
+ * @param key 保存的key
+ * @param value 保存的String数据
+ * @param saveTime 保存的时间,单位:秒
+ */
+ public void put(String key, String value, int saveTime) {
+ String values = Utils.newStringWithDateInfo(saveTime, value);
File file = mCache.newFile(key);
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file), 1024);
- out.write(value);
+ out.write(values);
} catch (IOException e) {
e.printStackTrace();
} finally {
@@ -144,17 +175,6 @@ public void put(String key, String value) {
}
}
- /**
- * 保存 String数据 到 缓存中
- *
- * @param key 保存的key
- * @param value 保存的String数据
- * @param saveTime 保存的时间,单位:秒
- */
- public void put(String key, String value, int saveTime) {
- put(key, Utils.newStringWithDateInfo(saveTime, value));
- }
-
/**
* 读取 String数据
*
@@ -196,6 +216,9 @@ public String getAsString(String key) {
}
}
+ public boolean getAsBoolean(String key) {
+ return Boolean.parseBoolean(getAsString(key));
+ }
// =======================================
// ============= JSONObject 数据 读写 ==============
// =======================================
@@ -206,7 +229,7 @@ public String getAsString(String key) {
* @param key 保存的key
* @param value 保存的JSON数据
*/
- public void put(String key, JSONObject value) {
+ public void put(String key, @NotNull JSONObject value) {
put(key, value.toString());
}
@@ -217,7 +240,7 @@ public void put(String key, JSONObject value) {
* @param value 保存的JSONObject数据
* @param saveTime 保存的时间,单位:秒
*/
- public void put(String key, JSONObject value, int saveTime) {
+ public void put(String key, @NotNull JSONObject value, int saveTime) {
put(key, value.toString(), saveTime);
}
@@ -248,7 +271,7 @@ public JSONObject getAsJSONObject(String key) {
* @param key 保存的key
* @param value 保存的JSONArray数据
*/
- public void put(String key, JSONArray value) {
+ public void put(String key, @NotNull JSONArray value) {
put(key, value.toString());
}
@@ -259,7 +282,7 @@ public void put(String key, JSONArray value) {
* @param value 保存的JSONArray数据
* @param saveTime 保存的时间,单位:秒
*/
- public void put(String key, JSONArray value, int saveTime) {
+ public void put(String key, @NotNull JSONArray value, int saveTime) {
put(key, value.toString(), saveTime);
}
@@ -388,13 +411,13 @@ public byte[] getAsBinary(String key) {
// =======================================
/**
- * 保存 Serializable数据 到 缓存中
+ * 保存 Serializable数据 到 缓存中 默认保存90天
*
* @param key 保存的key
* @param value 保存的value
*/
public void put(String key, Serializable value) {
- put(key, value, -1);
+ put(key, value, MAX_TIME_OUT);
}
/**
@@ -581,8 +604,7 @@ public class ACacheManager {
private final AtomicInteger cacheCount;
private final long sizeLimit;
private final int countLimit;
- private final Map lastUsageDates = Collections
- .synchronizedMap(new HashMap());
+ private final Map lastUsageDates = Collections.synchronizedMap(new HashMap<>());
protected File cacheDir;
private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {
@@ -598,22 +620,19 @@ private ACacheManager(File cacheDir, long sizeLimit, int countLimit) {
* 计算 cacheSize和cacheCount
*/
private void calculateCacheSizeAndCacheCount() {
- new Thread(new Runnable() {
- @Override
- public void run() {
- int size = 0;
- int count = 0;
- File[] cachedFiles = cacheDir.listFiles();
- if (cachedFiles != null) {
- for (File cachedFile : cachedFiles) {
- size += calculateSize(cachedFile);
- count += 1;
- lastUsageDates.put(cachedFile,
- cachedFile.lastModified());
- }
- cacheSize.set(size);
- cacheCount.set(count);
+ new Thread(() -> {
+ int size = 0;
+ int count = 0;
+ File[] cachedFiles = cacheDir.listFiles();
+ if (cachedFiles != null) {
+ for (File cachedFile : cachedFiles) {
+ size += calculateSize(cachedFile);
+ count += 1;
+ lastUsageDates.put(cachedFile,
+ cachedFile.lastModified());
}
+ cacheSize.set(size);
+ cacheCount.set(count);
}
}).start();
}
@@ -636,21 +655,24 @@ private void put(File file) {
}
cacheSize.addAndGet(valueSize);
- Long currentTime = System.currentTimeMillis();
+ long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
}
+ @NotNull
private File get(String key) {
File file = newFile(key);
- Long currentTime = System.currentTimeMillis();
+ long currentTime = System.currentTimeMillis();
file.setLastModified(currentTime);
lastUsageDates.put(file, currentTime);
return file;
}
- private File newFile(String key) {
+ @NotNull
+ @Contract("_ -> new")
+ private File newFile(@NotNull String key) {
return new File(cacheDir, key.hashCode() + "");
}
@@ -705,7 +727,7 @@ private long removeNext() {
return fileSize;
}
- private long calculateSize(File file) {
+ private long calculateSize(@NotNull File file) {
return file.length();
}
}
@@ -723,7 +745,7 @@ private static class Utils {
* @param str
* @return true:到期了 false:还没有到期
*/
- private static boolean isDue(String str) {
+ private static boolean isDue(@NotNull String str) {
return isDue(str.getBytes());
}
@@ -750,11 +772,13 @@ private static boolean isDue(byte[] data) {
return false;
}
+ @NotNull
private static String newStringWithDateInfo(int second, String strInfo) {
return createDateInfo(second) + strInfo;
}
- private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {
+ @NotNull
+ private static byte[] newByteArrayWithDateInfo(int second, @NotNull byte[] data2) {
byte[] data1 = createDateInfo(second).getBytes();
byte[] retdata = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, retdata, 0, data1.length);
@@ -762,6 +786,7 @@ private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) {
return retdata;
}
+ @Contract("null -> null")
private static String clearDateInfo(String strInfo) {
if (strInfo != null && hasDateInfo(strInfo.getBytes())) {
strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1,
@@ -778,11 +803,13 @@ private static byte[] clearDateInfo(byte[] data) {
return data;
}
+ @Contract(value = "null -> false", pure = true)
private static boolean hasDateInfo(byte[] data) {
return data != null && data.length > 15 && data[13] == '-'
&& indexOf(data, mSeparator) > 14;
}
+ @Nullable
private static String[] getDateInfoFromDate(byte[] data) {
if (hasDateInfo(data)) {
String saveDate = new String(copyOfRange(data, 0, 13));
@@ -793,6 +820,7 @@ private static String[] getDateInfoFromDate(byte[] data) {
return null;
}
+ @Contract(pure = true)
private static int indexOf(byte[] data, char c) {
for (int i = 0; i < data.length; i++) {
if (data[i] == c) {
@@ -802,6 +830,7 @@ private static int indexOf(byte[] data, char c) {
return -1;
}
+ @NotNull
private static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
@@ -815,9 +844,9 @@ private static byte[] copyOfRange(byte[] original, int from, int to) {
private static final char mSeparator = ' ';
private static String createDateInfo(int second) {
- String currentTime = System.currentTimeMillis() + "";
+ StringBuilder currentTime = new StringBuilder(System.currentTimeMillis() + "");
while (currentTime.length() < 13) {
- currentTime = "0" + currentTime;
+ currentTime.insert(0, "0");
}
return currentTime + "-" + second + mSeparator;
}
@@ -825,6 +854,7 @@ private static String createDateInfo(int second) {
/*
* Bitmap → byte[]
*/
+ @Contract("null -> null")
private static byte[] Bitmap2Bytes(Bitmap bm) {
if (bm == null) {
return null;
@@ -837,7 +867,8 @@ private static byte[] Bitmap2Bytes(Bitmap bm) {
/*
* byte[] → Bitmap
*/
- private static Bitmap Bytes2Bimap(byte[] b) {
+ @Nullable
+ private static Bitmap Bytes2Bimap(@NotNull byte[] b) {
if (b.length == 0) {
return null;
}
@@ -847,6 +878,7 @@ private static Bitmap Bytes2Bimap(byte[] b) {
/*
* Drawable → Bitmap
*/
+ @Contract("null -> null")
private static Bitmap drawable2Bitmap(Drawable drawable) {
if (drawable == null) {
return null;
@@ -870,6 +902,7 @@ private static Bitmap drawable2Bitmap(Drawable drawable) {
/*
* Bitmap → Drawable
*/
+ @Contract("null -> null")
@SuppressWarnings("deprecation")
private static Drawable bitmap2Drawable(Bitmap bm) {
if (bm == null) {
diff --git a/common_base/src/main/java/com/wss/common/utils/DateUtils.java b/common_base/src/main/java/com/wss/common/utils/DateUtils.java
index ae0a878..1e4f303 100644
--- a/common_base/src/main/java/com/wss/common/utils/DateUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/DateUtils.java
@@ -2,13 +2,21 @@
import android.annotation.SuppressLint;
import android.text.TextUtils;
+import android.util.Log;
-import com.wss.common.constants.Constant;
+import com.orhanobut.logger.Logger;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
import java.util.TimeZone;
/**
@@ -18,6 +26,16 @@
@SuppressLint("SimpleDateFormat")
public class DateUtils {
+ public static final String DATE_FORMAT = "yyyyMMddHH";
+ public static final String DATE_FORMAT_SLASH = "yyyy/MM/dd";
+ public static final String DATE_FORMAT_LINE = "yyyy-MM-dd";
+ public static final String DATE_FORMAT_TIME = "HH:mm:ss";
+ public static final String DATE_FORMAT_DEFAULT = DATE_FORMAT_SLASH + " " + DATE_FORMAT_TIME;
+ private static final int SECOND = 60;
+ private static final int DAY = 60;
+ private static final int MOUTH = 60;
+
+
/**
* 获取当前时间戳
*
@@ -33,9 +51,35 @@ public static long getCurrentTimeStamp() {
* @return String
*/
public static String getCurrentDateStr() {
- return getFormatDate(getCurrentTimeStamp(), Constant.DATE_FORMAT_LINE);
+ return getFormatDate(getCurrentTimeStamp(), DATE_FORMAT_LINE);
}
+ /**
+ * 获取格式化的当前系统时间
+ *
+ * @return String
+ */
+ public static String getCurrentDateStr(String pattern) {
+ return getFormatDate(getCurrentTimeStamp(), pattern);
+ }
+
+ /**
+ * 获取格式化时间
+ *
+ * @param date date
+ * @param pattern 格式化格式(默认yyyy-MM-dd HH:mm:ss)
+ */
+ @NotNull
+ public static String getFormatDate(Date date, String pattern) {
+ if (date == null) {
+ return "";
+ }
+ if (!ValidUtils.isValid(pattern)) {
+ pattern = DATE_FORMAT_DEFAULT;
+ }
+ SimpleDateFormat format = new SimpleDateFormat(pattern);
+ return format.format(date);
+ }
/**
* 获取格式化时间
@@ -49,7 +93,7 @@ public static String getFormatDate(long timeStamp, String pattern) {
timeStamp *= 1000;
}
if (TextUtils.isEmpty(pattern)) {
- pattern = Constant.DATE_FORMAT_DEFAULT;
+ pattern = DATE_FORMAT_DEFAULT;
}
SimpleDateFormat format = new SimpleDateFormat(pattern);
format.setTimeZone(TimeZone.getDefault());
@@ -64,21 +108,14 @@ public static String getFormatDate(long timeStamp, String pattern) {
* @param pattern pattern
* @return String
*/
- public static String getFormatDate(String stringDate, String pattern) {
+ public static String getFormatDate2(String stringDate, String pattern) {
if (TextUtils.isEmpty(stringDate)) {
return "";
}
- String parentPattern;
- if (stringDate.length() == 16) {
- parentPattern = "yyyy-MM-dd HH:mm";
- } else if (stringDate.length() == 19) {
- parentPattern = "yyyy-MM-dd HH:mm:ss";
- } else {
- return stringDate;
- }
- SimpleDateFormat sdf1 = new SimpleDateFormat(pattern);
try {
- return sdf1.format(new SimpleDateFormat(parentPattern).parse(stringDate));
+ SimpleDateFormat sdf1 = new SimpleDateFormat(pattern);
+ String sourcePattern = String.format("%s %s", DATE_FORMAT_LINE, DATE_FORMAT_TIME);
+ return sdf1.format(new SimpleDateFormat(sourcePattern).parse(stringDate));
} catch (ParseException e) {
e.printStackTrace();
}
@@ -86,39 +123,59 @@ public static String getFormatDate(String stringDate, String pattern) {
}
/**
- * 获取系统的时间
+ * 格式化返回日期时间
*
+ * @param stringDate stringDate
+ * @param pattern pattern
* @return String
*/
- public static String getCurrentTimeStr() {
- SimpleDateFormat fort = new SimpleDateFormat("HH:mm:ss");
- fort.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
- return fort.format(getCurrentTimeStamp());
+ public static String getFormatDate(String stringDate, String pattern) {
+ if (TextUtils.isEmpty(stringDate)) {
+ return "";
+ }
+ String parentPattern;
+ switch (stringDate.length()) {
+ case 10:
+ parentPattern = "yyyy-MM-dd";
+ break;
+ case 16:
+ parentPattern = "yyyy-MM-dd HH:mm";
+ break;
+ case 19:
+ parentPattern = "yyyy-MM-dd HH:mm:ss";
+ break;
+ default:
+ return stringDate;
+ }
+ SimpleDateFormat sdf1 = new SimpleDateFormat(pattern);
+ try {
+ return sdf1.format(new SimpleDateFormat(parentPattern).parse(stringDate));
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ return stringDate;
}
+
/**
- * 获取当前时间的下一天/ 前一天时间
- *
- * @param time time
- * @param day 正数为以后 负数为以前
- * @return
+ * 日期转日历
*/
- public static long getNextDayTimeStamp(long time, int day) {
- long timeStamp = 0;
- Calendar cal = Calendar.getInstance();
- Date date = new Date(time);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+ @NotNull
+ public static Calendar getFormatDate(String stringDate) {
+ SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_LINE);
+ Calendar calendar = Calendar.getInstance();
try {
- cal.setTime(date);
- cal.add(Calendar.DATE, 1);
- timeStamp = getStringToTimeStamp(sdf.format(cal.getTime()));
- } catch (Exception e) {
+ Date date = sdf.parse(stringDate);
+ if (date != null) {
+ calendar.setTime(date);
+ }
+ } catch (ParseException e) {
e.printStackTrace();
- return timeStamp;
}
- return timeStamp;
+ return calendar;
}
+
/**
* 根据字符串时间获取时间戳
*
@@ -134,7 +191,9 @@ public static long getStringToTimeStamp(String stringDate) {
}
try {
date = simpleDateFormat.parse(stringDate);
- timeStamp = date.getTime();
+ if (date != null) {
+ timeStamp = date.getTime();
+ }
} catch (ParseException e) {
return timeStamp;
}
@@ -142,32 +201,213 @@ public static long getStringToTimeStamp(String stringDate) {
}
/**
- * 根据当前时间获取问候语
+ * 时间转换
*
- * @return 问候语
+ * @param date 转换的时间戳
*/
- public static String getTimeToken() {
- Calendar calendar = Calendar.getInstance();
- int hour = calendar.get(Calendar.HOUR_OF_DAY);
- if (hour >= 0 && hour < 5) {
- return "凌晨";
- } else if (hour >= 5 && hour < 7) {
- return "清晨";
- } else if (hour >= 7 && hour < 9) {
- return "早上";
- } else if (hour >= 9 && hour < 12) {
- return "上午";
- } else if (hour >= 12 && hour < 14) {
- return "中午";
- } else if (hour >= 14 && hour < 17) {
- return "下午";
- } else if (hour >= 17 && hour < 19) {
- return "傍晚";
- } else if (hour >= 19 && hour < 21) {
- return "晚上";
- } else if (hour >= 21 && hour < 24) {
- return "深夜";
- }
- return "";
+ public static String dateTransformation(long date) {
+ long difference = (getCurrentTimeStamp() / 1000) - (date / 1000);
+ if (difference > 0) {
+ if (difference < SECOND * SECOND) {
+ long temp = difference / 60;
+ if (temp < 1) {
+ return "1分钟前";
+ }
+ return difference / 60 + "分钟前";
+ } else if (difference < DAY * SECOND * SECOND) {
+
+ return (int) (difference / 60 / 60) + "小时前";
+ } else if (difference < MOUTH * DAY * SECOND * SECOND) {
+
+ return (int) (difference / 60 / 60 / 24) + "日前";
+ } else {
+ return getFormatDate(date, DATE_FORMAT_SLASH);
+ }
+ } else {
+ return getFormatDate(date, DATE_FORMAT_SLASH);
+ }
}
+
+ /**
+ * 格式化时间
+ *
+ * @param dateStr 5月21日 17:00
+ * @return String
+ */
+ @Nullable
+ public static String getMessageDate(long dateStr) {
+ try {
+ Date date = new Date();
+ date.setTime(dateStr);
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ return String.format("%s月%s日%s:%s", (calendar.get(Calendar.MONTH) + 1),
+ calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * 根据月份返回中文
+ *
+ * @param month 月份
+ * @return 中文
+ */
+ @NotNull
+ @Contract(pure = true)
+ public static String getDateFormatMonth(int month) {
+ switch (month) {
+ case 1:
+ return "一月";
+ case 2:
+ return "二月";
+ case 3:
+ return "三月";
+ case 4:
+ return "四月";
+ case 5:
+ return "五月";
+ case 6:
+ return "六月";
+ case 7:
+ return "七月";
+ case 8:
+ return "八月";
+ case 9:
+ return "九月";
+ case 10:
+ return "十月";
+ case 11:
+ return "十一月";
+ case 12:
+ return "十二月";
+ default:
+ return "";
+ }
+ }
+
+ /**
+ * 计算两个时间的时间差
+ *
+ * @param time 时间
+ * @return 差值
+ */
+ public static long getTimeDifference(long time) {
+ long difference = System.currentTimeMillis() - time;
+ Log.e("时间差:", difference + "|" + difference / 1000);
+ return difference / 1000;
+ }
+
+ /**
+ * 获取当前时间往前往后n的日期
+ * eg: date ==null 默认是系统当前时间 否则以date为时间起点
+ * n > 0 往后
+ * n = 0 当前时间
+ * n < 0 往前
+ *
+ * @param date
+ * @param n
+ * @return
+ * @author zhangheng5@lenovo.com
+ */
+ @NotNull
+ public static List getBeforeDate(Date date, int n) {
+ List list = new ArrayList<>();
+ Calendar calender = Calendar.getInstance();
+ Date today = new Date();
+ if (null != date) {
+ today = date;
+ }
+ calender.setTime(today);
+
+ if (n > 0) {
+ for (int i = 0; i <= n; i++) {
+ calender.add(Calendar.DATE, i);
+ list.add(getFormatDate(calender.getTime(), DATE_FORMAT_LINE));
+ calender.setTime(today);
+ }
+ } else if (n < 0) {
+ for (int i = n; i <= 0; i++) {
+ calender.add(Calendar.DATE, i);
+ list.add(getFormatDate(calender.getTime(), DATE_FORMAT_LINE));
+ calender.setTime(today);
+ }
+ } else {
+ calender.add(Calendar.DATE, 0);
+ list.add(getFormatDate(calender.getTime(), DATE_FORMAT_LINE));
+ calender.setTime(today);
+ }
+
+ return list;
+ }
+
+ /**
+ * 根据时间戳判断是否是明天
+ *
+ * @param time 秒级 时间戳
+ * @return b
+ */
+ public static boolean isTomorrow(long time) {
+ Calendar curDate = Calendar.getInstance();
+ Calendar tomorrowCalendar = new GregorianCalendar(curDate
+ .get(Calendar.YEAR), curDate.get(Calendar.MONTH), curDate
+ .get(Calendar.DATE) + 1, 0, 0, 0);
+ long timeInMillis = tomorrowCalendar.getTimeInMillis();
+ return time >= tomorrowCalendar.getTimeInMillis() / 1000;
+ }
+
+ /**
+ * 格式化时间
+ *
+ * @param dateStr 时间字符串
+ * @return boolean
+ */
+ public static boolean isToday(String dateStr) {
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
+ Date date = null;
+ try {
+ date = format.parse(dateStr);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+ Calendar c1 = Calendar.getInstance();
+ c1.setTime(date);
+ int year1 = c1.get(Calendar.YEAR);
+ int month1 = c1.get(Calendar.MONTH) + 1;
+ int day1 = c1.get(Calendar.DAY_OF_MONTH);
+ Calendar c2 = Calendar.getInstance();
+ c2.setTime(new Date());
+ int year2 = c2.get(Calendar.YEAR);
+ int month2 = c2.get(Calendar.MONTH) + 1;
+ int day2 = c2.get(Calendar.DAY_OF_MONTH);
+ return year1 == year2 && month1 == month2 && day1 == day2;
+ }
+
+ /**
+ * 判断某一个时间是不是下午
+ *
+ * @param dateStr 时间字符串
+ * @return boolean
+ */
+ public static boolean isDatePm(String dateStr) {
+ int a = Integer.parseInt(getFormatDate2(dateStr, "HH"));
+ return a >= 12 && a < 24;
+ }
+
+
+ /**
+ * 获取afterMinute钟以前或者以后的时间
+ *
+ * @param afterMinute 之前传负数 之后传正数
+ * @return yyyy-MM-dd HH:mm:ss;
+ */
+ public static String getAfterMinuteTime(int afterMinute) {
+ SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date date = new Date(getCurrentTimeStamp() + 60 * 1000 * afterMinute);
+ return sd.format(date);
+ }
+
+
}
diff --git a/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java b/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java
index 001b5ca..3a89779 100644
--- a/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/EventBusUtils.java
@@ -1,14 +1,14 @@
package com.wss.common.utils;
+
import com.wss.common.bean.Event;
import org.greenrobot.eventbus.EventBus;
/**
- * Describe:EventBusUtils
+ * Describe:EventBus帮助类
* Created by 吴天强 on 2018/10/22.
*/
-
public class EventBusUtils {
/**
@@ -31,5 +31,18 @@ public static void unregister(Object subscriber) {
public static void sendEvent(Event event) {
EventBus.getDefault().post(event);
}
- //...
+
+ /**
+ * 发送普通事件
+ */
+ public static void sendEvent(String action) {
+ sendEvent(new Event(action));
+ }
+
+ /**
+ * 发送普通事件
+ */
+ public static void sendEvent(String action, Object data) {
+ sendEvent(new Event<>(action, data));
+ }
}
diff --git a/common_base/src/main/java/com/wss/common/utils/FileUtils.java b/common_base/src/main/java/com/wss/common/utils/FileUtils.java
index 5b35a8d..f4c885c 100644
--- a/common_base/src/main/java/com/wss/common/utils/FileUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/FileUtils.java
@@ -1,30 +1,50 @@
package com.wss.common.utils;
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.ContentUris;
import android.content.Context;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
-import android.support.annotation.Nullable;
-import android.support.v4.content.FileProvider;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
import com.orhanobut.logger.Logger;
import com.wss.common.base.BaseApplication;
+import org.jetbrains.annotations.NotNull;
+
import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedList;
+import androidx.annotation.Nullable;
+import androidx.core.content.FileProvider;
+
/**
* Describe:文件帮助类
* Created by 吴天强 on 2018/10/25.
*/
-
public class FileUtils {
- public static final String APPS_ROOT_DIR = getExternalStorePath() + File.separator + BaseApplication.getApplication().getPackageName();
- public static final String IMAGE_PATH = APPS_ROOT_DIR + "/Image";
- public static final String TEMP_PATH = APPS_ROOT_DIR + "/Temp";
- public static final String APP_CRASH_PATH = APPS_ROOT_DIR + "/AppCrash";
- public static final String FILE_PATH = APPS_ROOT_DIR + "/File";
+ public static final String APPS_ROOT_DIR = getExternalStorePath() + File.separator + BaseApplication.i().getPackageName();
+ public static final String IMAGE_PATH = APPS_ROOT_DIR + Constant.IMAGE;
+ public static final String TEMP_PATH = APPS_ROOT_DIR + Constant.TEMP;
+ public static final String APP_CRASH_PATH = APPS_ROOT_DIR + Constant.APP_CRASH;
+ public static final String FILE_PATH = APPS_ROOT_DIR + Constant.FILE;
+
+ /**
+ * 存放文件的目录
+ */
+ public interface Constant {
+ String IMAGE = "/Image";
+ String TEMP = "/Temp";
+ String FILE = "/File";
+ String APP_CRASH = "/AppCrash";
+ }
/**
@@ -49,6 +69,7 @@ public static boolean isExistExternalStore() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
+ @org.jetbrains.annotations.Nullable
private static File create(String path) {
if (!isExistExternalStore()) {
Logger.e("储存卡已拔出");
@@ -56,7 +77,7 @@ private static File create(String path) {
}
File directory = new File(path);
if (!directory.exists()) {
- directory.mkdir();
+ directory.mkdirs();
}
return directory;
}
@@ -67,8 +88,9 @@ private static File create(String path) {
* @return File
*/
@Nullable
- public static File getImagePath() {
- return create(IMAGE_PATH);
+ public static String getImagePath() {
+ File file = create(IMAGE_PATH);
+ return ValidUtils.isValid(file) ? file.getAbsolutePath() : "";
}
/**
@@ -77,8 +99,9 @@ public static File getImagePath() {
* @return File
*/
@Nullable
- public static File getTempPath() {
- return create(TEMP_PATH);
+ public static String getTempPath() {
+ File file = create(TEMP_PATH);
+ return ValidUtils.isValid(file) ? file.getAbsolutePath() : "";
}
/**
@@ -86,8 +109,10 @@ public static File getTempPath() {
*
* @return File
*/
- public static File getAppCrashPath() {
- return create(APP_CRASH_PATH);
+ @NotNull
+ public static String getAppCrashPath() {
+ File file = create(APP_CRASH_PATH);
+ return ValidUtils.isValid(file) ? file.getAbsolutePath() : "";
}
/**
@@ -95,8 +120,10 @@ public static File getAppCrashPath() {
*
* @return File
*/
- public static File getFilePath() {
- return create(FILE_PATH);
+ @NotNull
+ public static String getFilePath() {
+ File file = create(FILE_PATH);
+ return ValidUtils.isValid(file) ? file.getAbsolutePath() : "";
}
/**
@@ -116,6 +143,108 @@ public static Uri getUriForFile(Context context, File file) {
return fileUri;
}
+ /**
+ * URI转文件
+ *
+ * @param context context
+ * @param uri uri
+ * @return File
+ */
+ @org.jetbrains.annotations.Nullable
+ public static String uriToFile(@NotNull Activity context, @NotNull Uri uri) {
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+ String filePath = null;
+ if (DocumentsContract.isDocumentUri(context, uri)) {
+ // 如果是document类型的 uri, 则通过document id来进行处理
+ String documentId = DocumentsContract.getDocumentId(uri);
+ if (isMediaDocument(uri)) { // MediaProvider
+ // 使用':'分割
+ String type = documentId.split(":")[0];
+ String id = documentId.split(":")[1];
+
+ String selection = MediaStore.Images.Media._ID + "=?";
+ String[] selectionArgs = {id};
+ Uri contentUri = null;
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ } else if ("video".equals(type)) {
+ contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+ } else if ("audio".equals(type)) {
+ contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ }
+
+ filePath = getDataColumn(context, contentUri, selection, selectionArgs);
+ } else if (isDownloadsDocument(uri)) { // DownloadsProvider
+ Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.parseLong(documentId));
+ filePath = getDataColumn(context, contentUri, null, null);
+ } else if (isExternalStorageDocument(uri)) {
+ // ExternalStorageProvider
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+ if ("primary".equalsIgnoreCase(type)) {
+ filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
+ }
+ } //Log.e("路径错误");
+
+ } else if ("content".equalsIgnoreCase(uri.getScheme())) {
+ // 如果是 content 类型的 Uri
+ filePath = getDataColumn(context, uri, null, null);
+ } else if ("file".equals(uri.getScheme())) {
+ // 如果是 file 类型的 Uri,直接获取图片对应的路径
+ filePath = uri.getPath();
+ }
+ return filePath;
+ } else if ("file".equalsIgnoreCase(uri.getScheme())) {
+ return uri.getPath();
+ }
+ return "";
+ }
+
+
+ /**
+ * 获取数据库表中的 _data 列,即返回Uri对应的文件路径
+ *
+ * @return
+ */
+ private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+ String path = null;
+
+ String[] projection = new String[]{MediaStore.Images.Media.DATA};
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ int columnIndex = cursor.getColumnIndexOrThrow(projection[0]);
+ path = cursor.getString(columnIndex);
+ }
+ } catch (Exception e) {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return path;
+ }
+
+ /**
+ * @param uri the Uri to check
+ * @return Whether the Uri authority is MediaProvider
+ */
+ private static boolean isMediaDocument(@NotNull Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+ private static boolean isExternalStorageDocument(@NotNull Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ /**
+ * @param uri the Uri to check
+ * @return Whether the Uri authority is DownloadsProvider
+ */
+ private static boolean isDownloadsDocument(@NotNull Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
/**
* 获取目录下的文件列表
@@ -159,4 +288,15 @@ public static void deleteFile(String filesName) {
}
}
+ /**
+ * 读取文件的最后修改时间的方法
+ */
+ public static String getFileLastModifiedTime(File f) {
+ Calendar cal = Calendar.getInstance();
+ long time = f.lastModified();
+ @SuppressLint("SimpleDateFormat")
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ cal.setTimeInMillis(time);
+ return formatter.format(cal.getTime());
+ }
}
diff --git a/common_base/src/main/java/com/wss/common/utils/GroupUtils.java b/common_base/src/main/java/com/wss/common/utils/GroupUtils.java
new file mode 100644
index 0000000..4ad3bfc
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/GroupUtils.java
@@ -0,0 +1,150 @@
+package com.wss.common.utils;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Describe:Lis分组
+ * Created by 吴天强 on 2018-05-31 08:45
+ **/
+public class GroupUtils {
+ private static final String TAG = GroupUtils.class.getSimpleName();
+
+ /**
+ * 分组依据接口,用于集合分组时,获取分组依据
+ *
+ * @param
+ */
+ public interface GroupBy {
+ T groupBy(Object obj);
+ }
+
+ /**
+ * 待分组的集合
+ * 分组依据
+ *
+ * @param
+ * @param
+ * @return 分组数据
+ */
+ public static , D> Map> group(Collection colls, GroupBy gb) {
+ if (colls == null || colls.isEmpty()) {
+ Log.e(TAG, "分组集合不能为空");
+ return null;
+ }
+ if (gb == null) {
+ Log.e(TAG, " 分组依据接口不能为Null! ");
+ return null;
+ }
+ Iterator iter = colls.iterator();
+ Map> map = new HashMap<>();
+ while (iter.hasNext()) {
+ D d = iter.next();
+ T t = gb.groupBy(d);
+ if (map.containsKey(t)) {
+ map.get(t).add(d);
+ } else {
+ List list = new ArrayList<>();
+ list.add(d);
+ map.put(t, list);
+ }
+ }
+ return map;
+ }
+
+ /**
+ * 将List按照V的methodName方法返回值(返回值必须为K类型)分组,合入到Map>中
+ * 要保证入参的method必须为V的某一个有返回值的方法,并且该返回值必须为K类型
+ *
+ * @param list 待分组的列表
+ * @param map 存放分组后的map
+ * @param clazz 泛型V的类型
+ * @param methodName 方法名
+ */
+ public static void listGroup2Map(List list, Map> map, Class clazz, String methodName) {
+ // 入参非法行校验
+ if (null == list || null == map || null == clazz || TextUtils.isEmpty(methodName)) {
+ return;
+ }
+
+ // 获取方法
+ Method method = getMethodByName(clazz, methodName);
+ // 非空判断
+ if (null == method) {
+ return;
+ }
+ // 正式分组
+ listGroup2Map(list, map, method);
+ }
+
+ /**
+ * 根据类和方法名,获取方法对象
+ *
+ * @param clazz class
+ * @param methodName 风机组方法名
+ * @return Method
+ */
+ @Nullable
+ private static Method getMethodByName(Class> clazz, String methodName) {
+ Method method = null;
+ // 入参不能为空
+ if (null == clazz || TextUtils.isEmpty(methodName)) {
+ Log.e(TAG, "GroupUtils.getMethodByName 入参错误,clazz:" + clazz + " ;methodName:" + methodName);
+ return null;
+ }
+ try {
+ method = clazz.getDeclaredMethod(methodName);
+ } catch (Exception e) {
+ Log.e(TAG, "类获取方法失败");
+ }
+
+ return method;
+ }
+
+ /**
+ * 将List按照V的某个方法返回值(返回值必须为K类型)分组,合入到Map>中
+ * 要保证入参的method必须为V的某一个有返回值的方法,并且该返回值必须为K类型
+ *
+ * @param list 待分组的列表
+ * @param map 存放分组后的map
+ * @param method 方法
+ */
+ @SuppressWarnings("unchecked")
+ private static void listGroup2Map(List list, Map> map, Method method) {
+ // 入参非法行校验
+ if (null == list || null == map || null == method) {
+ Log.e(TAG, "GroupUtils.listGroup2Map 入参错误,list:" + list + " ;map:" + map + " ;method:" + method);
+ return;
+ }
+ try {
+ // 开始分组
+ Object key;
+ List listTmp;
+ for (V val : list) {
+ key = method.invoke(val);
+ listTmp = map.get(key);
+ if (null == listTmp) {
+ listTmp = new ArrayList<>();
+ map.put((K) key, listTmp);
+ }
+ listTmp.add(val);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, "数据分组异常" + e.getMessage());
+ }
+ }
+
+}
+
+
diff --git a/common_base/src/main/java/com/wss/common/utils/ImageUtils.java b/common_base/src/main/java/com/wss/common/utils/ImageUtils.java
index f089b07..fc42d9e 100644
--- a/common_base/src/main/java/com/wss/common/utils/ImageUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/ImageUtils.java
@@ -1,83 +1,347 @@
package com.wss.common.utils;
-import android.content.Context;
+import android.app.Activity;
+import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.media.ExifInterface;
-import android.support.annotation.Nullable;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.view.View;
import android.widget.ImageView;
+import android.widget.ScrollView;
-import com.squareup.picasso.Picasso;
+import com.bigkoo.convenientbanner.ConvenientBanner;
+import com.bigkoo.convenientbanner.listener.OnItemClickListener;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
+import com.bumptech.glide.request.RequestOptions;
+import com.wss.common.adapter.BannerImgAdapter;
import com.wss.common.base.R;
-import com.youth.banner.Banner;
-import com.youth.banner.BannerConfig;
-import com.youth.banner.Transformer;
-import com.youth.banner.loader.ImageLoader;
+import com.wss.common.manage.BlurTransformation;
+import com.wss.common.manage.GlideRoundTransform;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.Nullable;
+
/**
* Describe:图片工具类
* Created by 吴天强 on 2018/10/17.
*/
-
public class ImageUtils {
- public static void loadImage(Context context, String url, ImageView imageView) {
- Picasso.get()
+ /**
+ * 加载手机图片
+ * file
+ *
+ * @param imageView imageView
+ * @param file file
+ */
+ public static void loadImage(@NotNull ImageView imageView, File file) {
+ loadImage(imageView, file, R.color.color_999999);
+ }
+
+ /**
+ * 加载手机图片
+ *
+ * @param imageView imageView
+ * @param file file
+ * @param error 加载失败占位图
+ */
+ public static void loadImage(@NotNull ImageView imageView, File file, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
+ .load(file)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999)
+ .error(error)
+ .fallback(error))
+ .into(imageView);
+ }
+
+ /**
+ * 加载手机图片
+ *
+ * @param imageView imageView
+ */
+ public static void loadImage(@NotNull ImageView imageView, Bitmap bitmap) {
+ Glide.with(imageView.getContext())
+ .load(bitmap)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999))
+ .into(imageView);
+ }
+
+ /**
+ * 加载本地图片
+ *
+ * @param drawable drawable
+ * @param imageView imageView
+ */
+ public static void loadImage(@NotNull ImageView imageView, @DrawableRes int drawable) {
+ loadImage(imageView, drawable, R.color.color_999999);
+ }
+
+ /**
+ * 加载本地图片
+ *
+ * @param drawable drawable
+ * @param imageView imageView
+ * @param error 加载失败占位图
+ */
+ public static void loadImage(@NotNull ImageView imageView, int drawable, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
+ .load(drawable)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999)
+ .error(error)
+ .fallback(error))
+ .into(imageView);
+ }
+
+ /**
+ * 加载网络图片
+ *
+ * @param url url
+ * @param imageView imageView
+ */
+ public static void loadImage(ImageView imageView, String url) {
+ loadImage(imageView, url, R.color.color_999999);
+ }
+
+ /**
+ * 加载网络图片
+ *
+ * @param url url
+ * @param imageView imageView
+ * @param error 加载失败占位图
+ */
+ public static void loadImage(@NotNull ImageView imageView, String url, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
.load(url)
- .placeholder(R.drawable.bg_load_failed)
- .error(R.drawable.bg_load_failed)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999)
+ .error(error)
+ .fallback(error))
.into(imageView);
}
/**
- * 加载轮播图
+ * 加载圆形图片
*
- * @param banner 轮播图控件
- * @param images 图片集合
+ * @param url url
+ * @param imageView imageView
*/
- public static void loadBanner(Banner banner, List images) {
- if (banner == null || images == null) {
- return;
- }
- //如果没有图片集合 则给出一个默认占位图
- if (images.size() == 0) {
- images.add("R.drawable.bg_load_failed");
- }
- //设置banner样式
- banner.setBannerStyle(BannerConfig.CIRCLE_INDICATOR);
- //设置图片加载器
- banner.setImageLoader(new PicassoImageLoader());
- //设置banner动画效果
- banner.setBannerAnimation(Transformer.DepthPage);
- //设置自动轮播,默认为true
-// banner.isAutoPlay(false);
- //设置轮播时间
- banner.setDelayTime(2000);
- //设置指示器位置(当banner模式中有指示器时)
- banner.setIndicatorGravity(BannerConfig.RIGHT);
- //设置图片集合
- banner.setImages(images);
- //banner设置方法全部调用完毕时最后调用
- banner.start();
+ public static void loadImageCircle(ImageView imageView, String url) {
+ loadImageCircle(imageView, url, R.color.color_999999, R.color.color_999999);
+ }
+
+ /**
+ * 加载圆形图片
+ *
+ * @param url url
+ * @param imageView imageView
+ * @param error 加载失败占位图
+ */
+ public static void loadImageCircle(@NotNull ImageView imageView, String url, @DrawableRes int placeholder, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
+ .load(url)
+ .apply(RequestOptions.circleCropTransform()
+ .placeholder(placeholder)
+ .error(error)
+ .fallback(error))
+ .into(imageView);
}
/**
- * Banner图片加载器
+ * 加载圆角图片
+ *
+ * @param imageView ImageView
+ * @param url URL
+ * @param dp 圆角角度
*/
- private static class PicassoImageLoader extends ImageLoader {
+ public static void loadImageCircleBead(@NotNull ImageView imageView, String url, int dp) {
+ loadImageCircleBead(imageView, url, dp, R.color.color_999999);
+ }
- @Override
- public void displayImage(Context context, Object path, ImageView imageView) {
- loadImage(context, (String) path, imageView);
- }
+ /**
+ * 加载圆角图片
+ *
+ * @param imageView ImageView
+ * @param url URL
+ * @param dp 圆角角度
+ * @param error 加载失败占位图
+ */
+ public static void loadImageCircleBead(@NotNull ImageView imageView, String url, int dp, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
+ .load(url)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999)
+ .error(error)
+ .transform(new GlideRoundTransform(imageView.getContext(), dp)))
+ .into(imageView);
+ }
+
+ public static void loadImageTest(@NotNull ImageView imageView, String url, int dp) {
+
+ //设置图片圆角角度
+ RoundedCorners roundedCorners = new RoundedCorners(dp);
+ //通过RequestOptions扩展功能,override:采样率,因为ImageView就这么大,可以压缩图片,降低内存消耗
+ // RequestOptions options = RequestOptions.bitmapTransform(roundedCorners).override(300, 300);
+ RequestOptions options = RequestOptions.bitmapTransform(roundedCorners);
+ options.placeholder(R.color.color_999999);
+ Glide.with(imageView.getContext()).load(url).apply(options).into(imageView);
+
+ }
+
+ /**
+ * 加载圆角图片
+ *
+ * @param imageView ImageView
+ * @param file file
+ * @param dp 圆角角度
+ */
+ public static void loadImageCircleBead(@NotNull ImageView imageView, File file, int dp) {
+ loadImageCircleBead(imageView, file, dp, R.color.color_999999);
+ }
+
+ /**
+ * 加载圆角图片
+ *
+ * @param imageView ImageView
+ * @param file file
+ * @param dp 圆角角度
+ * @param error 加载失败占位图
+ */
+ public static void loadImageCircleBead(@NotNull ImageView imageView, File file, int dp, @DrawableRes int error) {
+ Glide.with(imageView.getContext())
+ .load(file)
+ .apply(new RequestOptions()
+ .placeholder(R.color.color_999999)
+ .error(error)
+ .transform(new GlideRoundTransform(imageView.getContext(), dp)))
+ .into(imageView);
+ }
+
+
+ /**
+ * 加载高斯模糊图
+ *
+ * @param imageView imageView
+ * @param drawable drawable
+ */
+ public static void loadImageBlur(ImageView imageView, int drawable) {
+ Glide.with(imageView)
+ .load(drawable)
+ .apply(RequestOptions.bitmapTransform(
+ new BlurTransformation(imageView.getContext(), 5f))
+ .error(R.color.theme))
+ .into(imageView);
+ }
+
+ /**
+ * 加载高斯模糊图
+ *
+ * @param imageView imageView
+ * @param drawable drawable
+ * @param error 加载失败占位图
+ */
+ public static void loadImageBlur(ImageView imageView, @DrawableRes int drawable, @DrawableRes int error) {
+ Glide.with(imageView)
+ .load(drawable)
+ .apply(RequestOptions.bitmapTransform(
+ new BlurTransformation(imageView.getContext(), 5f))
+ .placeholder(R.color.color_999999)
+ .error(error))
+ .into(imageView);
+ }
+
+ /**
+ * 加载高斯模糊图
+ *
+ * @param imageView imageView
+ * @param url url
+ */
+ public static void loadImageBlur(ImageView imageView, String url) {
+ Glide.with(imageView)
+ .load(url)
+ .apply(RequestOptions.bitmapTransform(
+ new BlurTransformation(imageView.getContext()))
+ .error(R.color.theme))
+ .into(imageView);
+ }
+
+ /**
+ * 加载高斯模糊图
+ *
+ * @param imageView imageView
+ * @param url url
+ * @param error 加载失败占位图
+ */
+ public static void loadImageBlur(ImageView imageView, String url, @DrawableRes int error) {
+ Glide.with(imageView)
+ .load(url)
+ .apply(RequestOptions.bitmapTransform(
+ new BlurTransformation(imageView.getContext()))
+ .placeholder(R.color.color_999999)
+ .error(error))
+ .into(imageView);
+ }
+
+
+ /**
+ * 加载圆形头像
+ *
+ * @param imageView imageView
+ * @param url 图片链接
+ */
+ public static void loadCircleHeader(ImageView imageView, String url) {
+ loadImageCircle(imageView, url, R.drawable.header_load_default, R.drawable.header_load_default);
+ }
+
+ /**
+ * 加载只有一张图的Banner
+ *
+ * @param banner banner控件
+ * @param imgUrl banner图片集合
+ * @param listener listener
+ */
+ public static void loadBanner(ConvenientBanner banner, List imgUrl, OnItemClickListener listener) {
+ banner.setPages(new BannerImgAdapter(), imgUrl)
+ .setPageIndicator(new int[]{R.drawable.shape_item_index_white, R.drawable.shape_item_index_red})
+ .setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT)
+ .setOnItemClickListener(listener)
+ .startTurning();
+ }
+
+ /**
+ * 加载只有一张图的Banner
+ *
+ * @param banner banner控件
+ * @param imgUrl banner图片集合
+ * @param listener listener
+ */
+ public static void loadBanner(ConvenientBanner banner, List imgUrl, boolean circle, OnItemClickListener listener) {
+ banner.setPages(new BannerImgAdapter(circle), imgUrl)
+ .setPageIndicator(new int[]{R.drawable.shape_item_index_white, R.drawable.shape_item_index_red})
+ .setPageIndicatorAlign(ConvenientBanner.PageIndicatorAlign.ALIGN_PARENT_RIGHT)
+ .setOnItemClickListener(listener)
+ .startTurning();
}
/**
@@ -91,10 +355,12 @@ public static File compressImage(String filePath) {
if (!FileUtils.isExistExternalStore()) {
return null;
}
- int quality = 100;
- Bitmap bm = getSmallBitmap(filePath);//获取一定尺寸的图片
- int degree = readPictureDegree(filePath);//获取相片拍摄角度
- if (degree != 0) {//旋转照片角度,防止头像横着显示
+ int quality = 100;//获取一定尺寸的图片
+ Bitmap bm = getSmallBitmap(filePath);
+ //获取相片拍摄角度
+ int degree = readPictureDegree(filePath);
+ if (degree != 0) {
+ //旋转照片角度,防止头像横着显示
bm = rotateBitmap(bm, degree);
}
File outputFile = null;
@@ -117,10 +383,14 @@ public static File compressImage(String filePath) {
/**
* 根据路径获得图片信息并按比例压缩,返回bitmap
+ *
+ * @param filePath 图片地址
+ * @return Bitmap
*/
public static Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
- options.inJustDecodeBounds = true;//只解析图片边沿,获取宽高
+ //只解析图片边沿,获取宽高
+ options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// 计算缩放比
options.inSampleSize = calculateInSampleSize(options, 480, 800);
@@ -129,15 +399,22 @@ public static Bitmap getSmallBitmap(String filePath) {
return BitmapFactory.decodeFile(filePath, options);
}
- public static int calculateInSampleSize(BitmapFactory.Options options,
- int reqWidth, int reqHeight) {
+ /**
+ * 计算缩放比
+ *
+ * @param options options
+ * @param reqWidth 宽
+ * @param reqHeight 高
+ * @return 缩放比
+ */
+ public static int calculateInSampleSize(@NotNull BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
- inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
+ inSampleSize = Math.min(heightRatio, widthRatio);
}
return inSampleSize;
}
@@ -145,8 +422,8 @@ public static int calculateInSampleSize(BitmapFactory.Options options,
/**
* 获取照片角度
*
- * @param path
- * @return
+ * @param path 图片地址
+ * @return int
*/
public static int readPictureDegree(String path) {
int degree = 0;
@@ -175,10 +452,11 @@ public static int readPictureDegree(String path) {
/**
* 旋转照片
*
- * @param bitmap
- * @param degress
- * @return
+ * @param bitmap bitmap
+ * @param degress 旋转角度
+ * @return Bitmap
*/
+ @Contract("null, _ -> null")
public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
if (bitmap != null) {
Matrix m = new Matrix();
@@ -187,7 +465,224 @@ public static Bitmap rotateBitmap(Bitmap bitmap, int degress) {
bitmap.getHeight(), m, true);
return bitmap;
}
- return bitmap;
+ return null;
+ }
+
+ /**
+ * 把View转成Bitmap 注意:改view必须是已经显示到页面上的
+ *
+ * @return Bitmap
+ */
+ public static Bitmap viewConversionBitmap(@NotNull View view, String color) {
+
+ int w = view.getWidth();
+ int h = view.getHeight();
+
+ Bitmap bmp = Bitmap.createBitmap(w, w, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bmp);
+
+ c.drawColor(Color.parseColor(color));
+ view.layout(0, 0, w, h);
+ view.draw(c);
+ return bmp;
+
+ }
+
+ /**
+ * 把View转成Bitmap 注意:改view必须是已经显示到页面上的
+ *
+ * @return Bitmap
+ */
+ public static Bitmap viewConversionBitmap(@NotNull ScrollView scrollView, String color) {
+
+ int height = 20;
+ //正确获取ScrollView
+ for (int i = 0; i < scrollView.getChildCount(); i++) {
+ height += scrollView.getChildAt(i).getHeight();
+ }
+
+ int w = scrollView.getWidth();
+
+ Bitmap bmp = Bitmap.createBitmap(w, height, Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(bmp);
+
+ c.drawColor(Color.parseColor(color));
+ scrollView.layout(0, 0, w, height);
+ scrollView.draw(c);
+ return bmp;
+
+ }
+
+ /**
+ * 把Bitmap转成图片
+ *
+ * @param bitmap bitmap
+ * @param imageName 文件名称
+ * @return 图片的本地地址
+ */
+ @org.jetbrains.annotations.Nullable
+ public static String bitmapSaveToImage(Bitmap bitmap, String imageName) {
+ FileOutputStream b = null;
+ String filePath = FileUtils.getImagePath() + File.separator + imageName + ".jpg";
+ try {
+ b = new FileOutputStream(filePath);
+ // 把数据写入文件
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);
+ return filePath;
+ } catch (Exception e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ if (b != null) {
+ b.flush();
+ b.close();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * 添加图片到系统相册
+ *
+ * @param activity activity
+ * @param filePath 图片路径
+ * @param fileName 图片名称
+ */
+ public static boolean addImageToAlbum(@NotNull Activity activity, String filePath, String fileName) {
+ try {
+ MediaStore.Images.Media.insertImage(activity.getContentResolver(), filePath, fileName, null);
+ activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + Environment.getExternalStorageDirectory().getPath())));
+ return true;
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+
+ /**
+ * 生成个人名片海报图片
+ *
+ * @param activity activity
+ * @param scrollView ScrollView
+ */
+ public static boolean generatePoster(Activity activity, ScrollView scrollView) {
+ String fileName = String.valueOf(DateUtils.getCurrentTimeStamp());
+ String filePath = ImageUtils.bitmapSaveToImage(ImageUtils.viewConversionBitmap(scrollView, "#F5F5F5"), fileName);
+ if (ValidUtils.isValid(filePath)) {
+ return addImageToAlbum(activity, filePath, fileName);
+ }
+ return false;
+ }
+
+ /**
+ * 生成个人名片海报图片
+ *
+ * @param activity activity
+ * @param scrollView ScrollView
+ */
+ public static String generatePosterPath(Activity activity, ScrollView scrollView) {
+ return ImageUtils.bitmapSaveToImage(ImageUtils.viewConversionBitmap(scrollView, "#F5F5F5"), String.valueOf(DateUtils.getCurrentTimeStamp()));
+ }
+
+ /**
+ * Bitmap转二进制流
+ *
+ * @param bitmap bitmap
+ * @return byte[]
+ */
+ @NotNull
+ public static byte[] getBitmapByte(@NotNull Bitmap bitmap) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
+ try {
+ out.flush();
+ out.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return out.toByteArray();
+ }
+
+ /**
+ * Bitmap转换成byte[]并且进行压缩,压缩到不大于maxkb
+ *
+ * @param bitmap bitmap
+ * @param maxKb 最大大小
+ * @return 字节数组
+ */
+ @NotNull
+ public static byte[] bitmapBytes(@NotNull Bitmap bitmap, int maxKb) {
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, output);
+ int options = 100;
+ while (output.toByteArray().length > maxKb && options != 10) {
+ output.reset(); //清空output
+ //这里压缩options%,把压缩后的数据存放到output中
+ bitmap.compress(Bitmap.CompressFormat.JPEG, options, output);
+ options -= 10;
+ }
+ return output.toByteArray();
+ }
+
+ /**
+ * 获取海报的图片二进制流
+ *
+ * @param layoutView 海报view
+ * @return byte[]
+ */
+ @NotNull
+ public static byte[] getPosterByte(View layoutView) {
+ return getBitmapByte(ImageUtils.viewConversionBitmap(layoutView, "#F5F5F5"));
+ }
+
+ /**
+ * 获取微信分享图片的缩略图
+ *
+ * @param image 图片流
+ * @return 图片流
+ */
+ @NotNull
+ public static byte[] getWXShareThumbImage(byte[] image) {
+ return bitmapBytes(getBitmapByBytes(image, 200, 300), 32);
+ }
+
+ /**
+ * 根据图片生成缩略图
+ *
+ * @param bytes 图片流
+ * @param maxHeight 最大高度
+ * @param maxWidth 最大宽度
+ * @return Bitmap
+ */
+ @NotNull
+ public static Bitmap getBitmapByBytes(byte[] bytes, int maxHeight, int maxWidth) {
+ //对于图片的二次采样,主要得到图片的宽与高
+ int width = 0;
+ int height = 0;
+ //默认缩放为1
+ int sampleSize = 1;
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ //仅仅解码边缘区域
+ options.inJustDecodeBounds = true;
+ //如果指定了inJustDecodeBounds,decodeByteArray将返回为空
+ BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
+ //得到宽与高
+ height = options.outHeight;
+ width = options.outWidth;
+
+ //图片实际的宽与高,根据默认最大大小值,得到图片实际的缩放比例
+ while ((height / sampleSize > maxHeight) || (width / sampleSize > maxWidth)) {
+ sampleSize *= 2;
+ }
+ //不再只加载图片实际边缘
+ options.inJustDecodeBounds = false;
+ //并且制定缩放比例
+ options.inSampleSize = sampleSize;
+ return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
}
diff --git a/common_base/src/main/java/com/wss/common/utils/JsonUtils.java b/common_base/src/main/java/com/wss/common/utils/JsonUtils.java
new file mode 100644
index 0000000..297a8fd
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/JsonUtils.java
@@ -0,0 +1,306 @@
+package com.wss.common.utils;
+
+import android.text.TextUtils;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * Describe:Gson 解析封装
+ * Created by 吴天强 on 2018/12/12.
+ */
+public class JsonUtils {
+
+ /**
+ * 对象转Json
+ *
+ * @param obj 对象
+ * @return json String
+ */
+ public static String toJson(Object obj) {
+ if (ValidUtils.isValid(obj)) {
+ return new Gson().toJson(obj);
+ }
+ return "{}";
+ }
+
+ /**
+ * 解析T对象
+ *
+ * @param json json
+ * @param type 目标类型
+ * @param 类型
+ * @return T
+ */
+ public static T getObject(String json, Class type) {
+ return new Gson().fromJson(json, type);
+ }
+
+ /**
+ * 解析String
+ *
+ * @param json json
+ * @param key key
+ * @return String
+ */
+ @Contract("null, _ -> !null")
+ public static String getString(JsonObject json, String key) {
+ if (json == null) {
+ return "";
+ }
+ JsonElement jsonElement = json.get(key);
+ if (jsonElement == null) {
+ return "";
+ }
+ return jsonElement.getAsString();
+ }
+
+ /**
+ * 解析String
+ *
+ * @param element json
+ * @return String
+ */
+ @Contract("null, _ -> !null")
+ public static String getString(JsonElement element, String key) {
+ if (element == null) {
+ return "";
+ }
+ return getString(element.getAsJsonObject(), key);
+ }
+
+ /**
+ * 解析String
+ *
+ * @param json json
+ * @param key key
+ * @return String
+ */
+ public static String getString(String json, String key) {
+ if (!isJsonObject(json)) {
+ return "";
+ }
+ JsonElement jsonElement = getJsonObject(json).get(key);
+ if (jsonElement == null) {
+ return "";
+ }
+ //判断json对象是否为Object
+ if (jsonElement.isJsonObject()) {
+ JsonObject asJsonObject = jsonElement.getAsJsonObject();
+ return asJsonObject.toString();
+ }
+ //判断json对象是否为数组
+ if (jsonElement.isJsonArray()) {
+ JsonArray asJsonArray = jsonElement.getAsJsonArray();
+ return asJsonArray.toString();
+ }
+ return jsonElement.getAsString();
+ }
+
+
+ /**
+ * 解析boolean
+ *
+ * @param json json
+ * @param key key
+ * @return boolean
+ */
+ @Contract("null, _ -> false")
+ public static boolean getBoolean(String json, String key) {
+ if (json == null) {
+ return false;
+ }
+ JsonElement jsonElement = getJsonObject(json).get(key);
+ return jsonElement != null && jsonElement.getAsBoolean();
+ }
+
+ /**
+ * 解析int
+ *
+ * @param json json
+ * @param key key
+ * @return String
+ */
+ public static int getInt(String json, String key) {
+ JsonElement jsonElement = getJsonObject(json).get(key);
+ if (jsonElement == null) {
+ return 0;
+ }
+ return jsonElement.getAsInt();
+ }
+
+ /**
+ * 解析int
+ *
+ * @param json json
+ * @param key key
+ * @return boolean
+ */
+ public static int getInt(JsonObject json, String key) {
+ if (json == null) {
+ return 0;
+ }
+ JsonElement jsonElement = json.get(key);
+ if (jsonElement == null) {
+ return 0;
+ }
+ return jsonElement.getAsInt();
+ }
+
+
+ /**
+ * 解析JsonObject
+ *
+ * @param json json
+ * @return JsonArray
+ */
+ public static JsonObject getJsonObject(String json) {
+ if (TextUtils.isEmpty(json)) {
+ return new JsonObject();
+ }
+ return new JsonParser().parse(json).getAsJsonObject();
+ }
+
+ /**
+ * 解析JsonArray
+ *
+ * @param json json
+ * @param key key
+ * @return JsonArray
+ */
+ @Contract("null, _ -> new")
+ public static JsonArray getJsonArray(JsonObject json, String key) {
+ if (json == null) {
+ return new JsonArray();
+ }
+ JsonElement jsonElement = json.get(key);
+ if (jsonElement == null) {
+ return new JsonArray();
+ }
+ return jsonElement.getAsJsonArray();
+ }
+
+
+ /**
+ * 解析Map
+ *
+ * @param json json
+ * @return List
+ */
+ @NotNull
+ public static LinkedHashMap getMap(@NotNull String json) {
+ LinkedHashMap result = new LinkedHashMap<>();
+ try {
+ JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
+ result.putAll(new Gson().fromJson(jsonObject, new TypeToken>() {
+ }.getType()));
+ } catch (JsonSyntaxException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 解析List
+ *
+ * @param json json
+ * @param clazz clazz
+ * @return List
+ */
+ public static List getList(String json, Class clazz) {
+ if (!ValidUtils.isValid(json)) {
+ return new ArrayList<>();
+ }
+ List list = null;
+ try {
+ list = new ArrayList<>();
+ Type type = new TypeToken>() {
+ }.getType();
+ List jsonObjects = new Gson().fromJson(json, type);
+ if (ValidUtils.isValid(jsonObjects)) {
+ for (JsonObject jsonObject : jsonObjects) {
+ list.add(new Gson().fromJson(jsonObject, clazz));
+ }
+ }
+ } catch (JsonSyntaxException e) {
+ e.printStackTrace();
+ }
+ return list;
+ }
+
+ /**
+ * 解析List
+ *
+ * @param json json
+ * @return List
+ */
+ public static List getList(String json) {
+ if (!isJsonArray(json)) {
+ return new ArrayList<>();
+ }
+ return new Gson().fromJson(json, new TypeToken>() {
+ }.getType());
+ }
+
+ /**
+ * 判断是否JSON数组
+ *
+ * @param json json
+ * @return boolean
+ */
+ public static boolean isJsonArray(String json) {
+ JsonElement jsonElement = getJsonElement(json);
+ if (jsonElement == null) {
+ return false;
+ }
+ return jsonElement.isJsonArray();
+ }
+
+ /**
+ * 判断是否JSON对象
+ *
+ * @param json json
+ * @return boolean
+ */
+ public static boolean isJsonObject(String json) {
+ JsonElement jsonElement = getJsonElement(json);
+ if (jsonElement == null) {
+ return false;
+ }
+ return jsonElement.isJsonObject();
+ }
+
+ /**
+ * 获取JsonElement
+ *
+ * @param json json
+ * @return JsonElement
+ */
+ @Nullable
+ private static JsonElement getJsonElement(String json) {
+ JsonElement jsonElement;
+ if (!ValidUtils.isValid(json)) {
+ return null;
+ }
+ try {
+ jsonElement = new JsonParser().parse(json);
+ } catch (Exception e) {
+ return null;
+ }
+ return jsonElement;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java b/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java
index a4f2426..a6c3af4 100644
--- a/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/KeyboardUtils.java
@@ -4,13 +4,20 @@
import android.view.View;
import android.view.inputmethod.InputMethodManager;
+import org.jetbrains.annotations.NotNull;
+
/**
* Describe:键盘辅助类
* Created by 吴天强 on 2017/11/2.
*/
public class KeyboardUtils {
- public static void showKeyboard(View view) {
+ /**
+ * 显示键盘
+ *
+ * @param view view
+ */
+ public static void showKeyboard(@NotNull View view) {
InputMethodManager imm = (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
@@ -19,19 +26,16 @@ public static void showKeyboard(View view) {
}
}
- public static void hideKeyboard(View view) {
+ /**
+ * 隐藏键盘
+ *
+ * @param view view
+ */
+ public static void hideKeyboard(@NotNull View view) {
InputMethodManager imm = (InputMethodManager) view.getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
-
- public static void toggleSoftInput(View view) {
- InputMethodManager imm = (InputMethodManager) view.getContext()
- .getSystemService(Context.INPUT_METHOD_SERVICE);
- if (imm != null) {
- imm.toggleSoftInput(0, 0);
- }
- }
}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java
index 15d12d4..8768e44 100644
--- a/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/MoneyUtils.java
@@ -10,7 +10,6 @@
* Describe:金钱工具类
* Created by 吴天强 on 2017/11/24.
*/
-
public class MoneyUtils {
/**
* 计算类
@@ -20,32 +19,32 @@ public static class Algorithm {
/**
* 金钱加法
*
- * @param v1
- * @param v2
- * @return
+ * @param value1 参数1
+ * @param value2 参数2
+ * @return 结果
*/
- public static String add(String v1, String v2) {
- BigDecimal b1 = new BigDecimal(v1);
- BigDecimal b2 = new BigDecimal(v2);
+ public static String add(Object value1, Object value2) {
+ BigDecimal b1 = new BigDecimal(String.valueOf(value1));
+ BigDecimal b2 = new BigDecimal(String.valueOf(value2));
return b1.add(b2).toString();
}
/**
* 金钱减法
*
- * @param v1
- * @param v2
- * @return
+ * @param value1 参数1
+ * @param value2 参数2
+ * @return 结果
*/
- public static String subtract(String v1, String v2) {
- if (TextUtils.isEmpty(v1)) {
- v1 = "0";
+ public static String subtract(String value1, String value2) {
+ if (TextUtils.isEmpty(value1)) {
+ value1 = "0";
}
- if (TextUtils.isEmpty(v2)) {
- v2 = "0";
+ if (TextUtils.isEmpty(value2)) {
+ value2 = "0";
}
- BigDecimal b1 = new BigDecimal(v1);
- BigDecimal b2 = new BigDecimal(v2);
+ BigDecimal b1 = new BigDecimal(value1);
+ BigDecimal b2 = new BigDecimal(value2);
return b1.subtract(b2).toString();
}
@@ -53,25 +52,25 @@ public static String subtract(String v1, String v2) {
/**
* 金钱乘法
*
- * @param v1
- * @param v2
- * @return
+ * @param value1 参数1
+ * @param value2 参数2
+ * @return 结果
*/
- public static String multiply(String v1, String v2) {
- return multiply(v1, v2, 0);
+ public static String multiply(String value1, String value2) {
+ return multiply(value1, value2, 0);
}
/**
* 金钱乘法
*
- * @param v1 乘数
- * @param v2 被乘数
- * @param scale 小数点保留位数
- * @return
+ * @param value1 乘数
+ * @param value2 被乘数
+ * @param scale 小数点保留位数
+ * @return 结果
*/
- public static String multiply(String v1, String v2, int scale) {
- BigDecimal b1 = new BigDecimal(v1);
- BigDecimal b2 = new BigDecimal(v2);
+ public static String multiply(String value1, String value2, int scale) {
+ BigDecimal b1 = new BigDecimal(value1);
+ BigDecimal b2 = new BigDecimal(value2);
BigDecimal result = b1.multiply(b2);
result = result.setScale(scale, BigDecimal.ROUND_HALF_UP);
return result.toString();
@@ -80,13 +79,13 @@ public static String multiply(String v1, String v2, int scale) {
/**
* 金钱除法
*
- * @param v1
- * @param v2
- * @return
+ * @param value1 参数1
+ * @param value2 参数2
+ * @return 结果
*/
- public static String divide(String v1, String v2) {
- BigDecimal b1 = new BigDecimal(v1);
- BigDecimal b2 = new BigDecimal(v2);
+ public static String divide(String value1, String value2) {
+ BigDecimal b1 = new BigDecimal(value1);
+ BigDecimal b2 = new BigDecimal(value2);
return b1.divide(b2, BigDecimal.ROUND_HALF_UP).toString();
}
}
@@ -98,7 +97,7 @@ public static String divide(String v1, String v2) {
* @return String
*/
public static String formatPrice(String textPrice) {
- return formatPrice(Double.valueOf(textPrice) / 100);
+ return formatPrice(Double.parseDouble(textPrice) / 100);
}
/**
@@ -108,13 +107,6 @@ public static String formatPrice(String textPrice) {
* @return String
*/
public static String formatPrice(double price) {
- if (price > 0 && price < 1) {
- String temp = String.valueOf(price);
- if (temp.contains(".") && temp.substring(temp.indexOf(".") + 1, temp.length()).length() <= 1) {
- return String.format("%s%s", price, 0);
- }
- return String.format("%s", price);
- }
if (price <= 0) {
return "0.00";
}
@@ -123,4 +115,28 @@ public static String formatPrice(double price) {
return String.format("%s", format.format(price));
}
+ /**
+ * 将金钱转成显示的格式¥xx.xx如此格式
+ *
+ * @param price 单位为元的金额
+ * @return String
+ */
+ public static String formatPriceT(double price) {
+ if (price <= 0) {
+ return "0.00";
+ }
+ DecimalFormat format = new DecimalFormat("0.00");
+ format.setRoundingMode(RoundingMode.FLOOR);
+ return String.format("%s", format.format(price));
+ }
+ /**
+ * 将金钱转成显示的格式¥xx.xx如此格式
+ *
+ * @param textPrice 单位为分的金额
+ * @return String
+ */
+ public static String formatPriceT(String textPrice) {
+ return formatPriceT(Double.parseDouble(textPrice) / 10000);
+ }
+
}
diff --git a/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java b/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java
index d2fa331..047924f 100644
--- a/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java
+++ b/common_base/src/main/java/com/wss/common/utils/NetworkUtil.java
@@ -6,8 +6,15 @@
import android.net.NetworkInfo;
import android.telephony.TelephonyManager;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Enumeration;
import java.util.List;
+import androidx.annotation.NonNull;
+
/**
* Describe:网络状态工具类
* Created by 吴天强 on 2018/10/25.
@@ -18,18 +25,15 @@ public class NetworkUtil {
* 是否有可用网络
*
* @param context context
- * @return
+ * @return boolean
*/
- public static boolean isNetworkAvailable(Context context) {
- ConnectivityManager connectivity = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
+ public static boolean isNetworkEnabled(@NonNull Context context) {
+ ConnectivityManager connectivity = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
- if (info != null) {
- for (int i = 0; i < info.length; i++) {
- if (info[i].getState() == NetworkInfo.State.CONNECTED) {
- return true;
- }
+ for (NetworkInfo networkInfo : info) {
+ if (networkInfo.getState() == NetworkInfo.State.CONNECTED) {
+ return true;
}
}
}
@@ -37,60 +41,97 @@ public static boolean isNetworkAvailable(Context context) {
}
/**
- * gps能用?
+ * gps能用
*
- * @param context context
- * @return
+ * @param context ctx
+ * @return boolean
*/
- public static boolean isGpsEnabled(Context context) {
- LocationManager locationManager = ((LocationManager) context
- .getSystemService(Context.LOCATION_SERVICE));
- List accessibleProviders = locationManager.getProviders(true);
- return accessibleProviders != null && accessibleProviders.size() > 0;
+ public static boolean isGpsEnabled(@NonNull Context context) {
+ LocationManager locationManager = ((LocationManager) context.getSystemService(Context.LOCATION_SERVICE));
+ if (locationManager != null) {
+ List accessibleProviders = locationManager.getProviders(true);
+ return accessibleProviders.size() > 0;
+ }
+ return false;
}
/**
* Wifi是否可用
*
* @param context context
- * @return
+ * @return boolean
*/
- public static boolean isWifiEnabled(Context context) {
- ConnectivityManager mgrConn = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- TelephonyManager mgrTel = (TelephonyManager) context
- .getSystemService(Context.TELEPHONY_SERVICE);
- return ((mgrConn.getActiveNetworkInfo() != null && mgrConn
- .getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) || mgrTel
- .getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS);
+ public static boolean isWifiEnabled(@NonNull Context context) {
+ ConnectivityManager mgrConn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (mgrConn != null && mgrConn.getActiveNetworkInfo() != null &&
+ mgrConn.getActiveNetworkInfo().getState() == NetworkInfo.State.CONNECTED) {
+ return true;
+ }
+ TelephonyManager mgrTel = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ return mgrTel != null && mgrTel.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS;
}
/**
* 当前网络是否为Wifi
*
* @param context context
- * @return
+ * @return boolean
*/
- public static boolean isWifi(Context context) {
- ConnectivityManager connectivityManager = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
- return activeNetInfo != null
- && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
+ public static boolean isWifi(@NonNull Context context) {
+ ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivityManager != null) {
+ NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
+ return activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI;
+ }
+ return false;
}
/**
- * 当前网络是否为收集数据
+ * 当前网络是否为移动数据
*
* @param context context
- * @return
+ * @return boolean
+ */
+ public static boolean isMobile(@NonNull Context context) {
+ ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivityManager != null) {
+ NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
+ return activeNetInfo != null && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE;
+ }
+ return false;
+ }
+
+ /**
+ * 获取当前网络IP
+ *
+ * @return 网络IP
+ */
+ public static String getIpAddress() {
+ try {
+ for (Enumeration enNetI = NetworkInterface.getNetworkInterfaces(); enNetI
+ .hasMoreElements(); ) {
+ NetworkInterface netI = enNetI.nextElement();
+ for (Enumeration enumIpAddr = netI.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+ InetAddress inetAddress = enumIpAddr.nextElement();
+ if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
+ return inetAddress.getHostAddress();
+ }
+ }
+ }
+ } catch (SocketException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 检查是否为连接
+ *
+ * @param url url
+ * @return boolean
*/
- public static boolean is3G(Context context) {
- ConnectivityManager connectivityManager = (ConnectivityManager) context
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
- return activeNetInfo != null
- && activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE;
+ public static boolean isLink(String url) {
+ return ValidUtils.isValid(url) && (url.startsWith("http") || url.startsWith("https"));
}
}
diff --git a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java
index c9b66dd..d941132 100644
--- a/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/PermissionsUtils.java
@@ -1,59 +1,137 @@
package com.wss.common.utils;
+import android.Manifest;
import android.app.Activity;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import java.util.ArrayList;
+import com.hjq.permissions.OnPermission;
+import com.hjq.permissions.Permission;
+import com.hjq.permissions.XXPermissions;
+import com.wss.common.base.R;
+
import java.util.List;
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.schedulers.Schedulers;
+
/**
- * Describe:6.0动态权限管理帮助类
+ * Describe:6.0 + 动态权限管理帮助类
* Created by 吴天强 on 2018/10/25.
*/
-
public class PermissionsUtils {
+ /**
+ * 授权所有权限
+ *
+ * @param activity activity
+ */
+ public static void authorizationAllPermissions(Activity activity) {
+ XXPermissions.with(activity)
+ .request(new OnPermission() {
+ @Override
+ public void hasPermission(List granted, boolean isAll) {
+ }
+
+ @Override
+ public void noPermission(List denied, boolean quick) {
+ }
+ });
+ }
/**
- * 判断权限
+ * 检查权限
*
- * @param context context
- * @param permissions 权限列表
+ * @param activity activity
+ * @param permissions 权限组
+ * @return Observable
*/
- public static void checkPermissions(Activity context, String... permissions) {
+ public static Observable checkPermissions(Activity activity, String... permissions) {
+ return Observable.create(
+ subscriber -> {
+ if (XXPermissions.isHasPermission(activity, permissions)) {
+ subscriber.onNext(true);
+ } else {
+ XXPermissions.with(activity)
+ .permission(permissions)
+ .request(new OnPermission() {
+ @Override
+ public void hasPermission(List granted, boolean isAll) {
+ subscriber.onNext(isAll);
+ }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- List permissionsList = new ArrayList<>();
- if (permissions != null && permissions.length != 0) {
- for (String permission : permissions) {
- if (!isHavePermissions(context, permission)) {
- permissionsList.add(permission);
+ @Override
+ public void noPermission(List denied, boolean quick) {
+ subscriber.onNext(false);
+ ToastUtils.show(activity, activity.getString(R.string.authorise_necessary_authorities));
+ }
+ });
}
- }
- // 遍历完后申请
- applyPermissions(context, permissionsList);
- }
- }
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+
+ /**
+ * 检查相机权限
+ *
+ * @param activity activity
+ * @return Observable
+ */
+ public static Observable checkCamera(Activity activity) {
+ return checkPermissions(activity, Permission.CAMERA, Permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+
+ /**
+ * 检查文件读写权限
+ *
+ * @param activity activity
+ * @return boolean
+ */
+ public static Observable checkStorage(Activity activity) {
+ String[] storage = {
+ Permission.READ_EXTERNAL_STORAGE,
+ Permission.WRITE_EXTERNAL_STORAGE};
+ return checkPermissions(activity, storage);
+ }
+
+
+ /**
+ * 检查录音相关权限
+ */
+ public static Observable checkRecord(Activity activity) {
+ return checkPermissions(activity, Permission.READ_EXTERNAL_STORAGE,
+ Permission.WRITE_EXTERNAL_STORAGE,
+ Permission.RECORD_AUDIO);
}
/**
- * 检查是否授权某权限
+ * 检查拨打电话相关权限
*/
- private static boolean isHavePermissions(Activity context, String permissions) {
- return ContextCompat.checkSelfPermission(context, permissions) == PackageManager.PERMISSION_GRANTED;
+ public static Observable checkCallPhone(Activity activity) {
+ return checkPermissions(activity, Permission.CALL_PHONE);
}
/**
- * 申请权限
+ * 检查定位权限
+ *
+ * @param activity activity
+ * @return boolean
*/
- private static void applyPermissions(Activity context, List permissions) {
- if (!permissions.isEmpty()) {
- ActivityCompat.requestPermissions(context, permissions.toArray(new String[permissions.size()]), 1);
- }
+ public static Observable checkLocation(Activity activity) {
+ return checkPermissions(activity, Permission.ACCESS_FINE_LOCATION,
+ Permission.ACCESS_COARSE_LOCATION, Permission.RECORD_AUDIO);
}
+ /**
+ * 允许锁屏状态下,app在后台运行
+ *
+ * @param activity activity
+ * @return boolean
+ */
+ public static Observable checkWakeLock(Activity activity) {
+ return checkPermissions(activity, Manifest.permission.WAKE_LOCK);
+ }
}
diff --git a/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java b/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java
new file mode 100644
index 0000000..a47b278
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/PhoneUtils.java
@@ -0,0 +1,46 @@
+package com.wss.common.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.net.Uri;
+
+import com.wss.common.base.BaseApplication;
+
+/**
+ * description: 拨打电话工具类
+ *
+ * @author 杨伟-tony
+ * create by 2020/5/22 11:26
+ */
+public class PhoneUtils {
+ /**
+ * 拨打电话
+ * ps:调起拨号盘
+ *
+ * @param phoneNum 电话号码
+ */
+ public static void callPhoneWaitFor(String phoneNum) {
+ Intent intent = new Intent(Intent.ACTION_DIAL);
+ Uri data = Uri.parse("tel:" + phoneNum);
+ intent.setData(data);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ BaseApplication.i().startActivity(intent);
+
+ }
+
+ /**
+ * 拨打电话
+ * 吊起拨号盘 直接拨打电话
+ *
+ * @param phoneNum 电话号码
+ */
+ @SuppressLint("MissingPermission")
+ public static void callPhoneDirect(String phoneNum) {
+ Intent intent = new Intent(Intent.ACTION_CALL);
+ Uri data = Uri.parse("tel:" + phoneNum);
+ intent.setData(data);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ BaseApplication.i().startActivity(intent);
+ }
+
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/PxUtils.java b/common_base/src/main/java/com/wss/common/utils/PxUtils.java
index 005da2a..6522fa6 100644
--- a/common_base/src/main/java/com/wss/common/utils/PxUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/PxUtils.java
@@ -1,29 +1,43 @@
package com.wss.common.utils;
import android.content.Context;
+import android.graphics.Paint;
+import android.view.View;
+
+import com.wss.common.base.BaseApplication;
+
+import androidx.annotation.NonNull;
/**
* Describe:尺寸工具类
* Created by 吴天强 on 2017/9/19.
*/
-
public class PxUtils {
/**
* 得到设备屏幕的宽度
+ *
+ * @param context ctx
+ * @return int
*/
- public static int getScreenWidth(Context context) {
+ public static int getScreenWidth(@NonNull Context context) {
return context.getResources().getDisplayMetrics().widthPixels;
}
/**
* 得到设备屏幕的高度
+ *
+ * @param context ctx
+ * @return int
*/
- public static int getScreenHeight(Context context) {
+ public static int getScreenHeight(@NonNull Context context) {
return context.getResources().getDisplayMetrics().heightPixels;
}
/**
* 得到设备的密度
+ *
+ * @param context ctx
+ * @return float
*/
public static float getScreenDensity(Context context) {
return context.getResources().getDisplayMetrics().density;
@@ -31,33 +45,64 @@ public static float getScreenDensity(Context context) {
/**
* 把密度转换为像素
+ *
+ * @param dpValue dp值
+ * @return int
*/
- public static int dp2px(Context context, float dipValue) {
- final float scale = getScreenDensity(context);
- return (int) (dipValue * scale + 0.5);
+ public static int dp2px(float dpValue) {
+ float scale = getScreenDensity(BaseApplication.i());
+ return (int) (dpValue * scale + 0.5);
}
/**
* 将像素转换成dp
*
- * @param context
- * @param pxValue
- * @return
+ * @param pxValue px值
+ * @return int
*/
- public static int px2dp(Context context, float pxValue) {
- final float scale = context.getResources().getDisplayMetrics().density;
+ public static int px2dp(float pxValue) {
+ float scale = getScreenDensity(BaseApplication.i());
return (int) (pxValue / scale + 0.5f);
}
/**
* 将sp值转换为px值,保证文字大小不变
*
- * @param context context
- * @param spValue
- * @return
+ * @param spValue sp值
+ * @return int
*/
- public static int sp2px(Context context, float spValue) {
- final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
+ public static int sp2px(float spValue) {
+ float fontScale = getScreenDensity(BaseApplication.i());
return (int) (spValue * fontScale + 0.5f);
}
+
+ /**
+ * 测量 View
+ *
+ * @param measureSpec
+ * @param defaultSize View 的默认大小
+ * @return
+ */
+ public static int measure(int measureSpec, int defaultSize) {
+ int result = defaultSize;
+ int specMode = View.MeasureSpec.getMode(measureSpec);
+ int specSize = View.MeasureSpec.getSize(measureSpec);
+
+ if (specMode == View.MeasureSpec.EXACTLY) {
+ result = specSize;
+ } else if (specMode == View.MeasureSpec.AT_MOST) {
+ result = Math.min(result, specSize);
+ }
+ return result;
+ }
+ /**
+ * 测量文字高度
+ *
+ * @param paint
+ * @return
+ */
+ public static float measureTextHeight(Paint paint) {
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ return (Math.abs(fontMetrics.ascent) - fontMetrics.descent);
+ }
}
diff --git a/common_base/src/main/java/com/wss/common/utils/RomUtil.java b/common_base/src/main/java/com/wss/common/utils/RomUtil.java
new file mode 100644
index 0000000..ecc138b
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/RomUtil.java
@@ -0,0 +1,152 @@
+package com.wss.common.utils;
+
+import android.os.Build;
+import android.text.TextUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * Describe:判断手机ROM类型
+ * Created by 吴天强 on 2020/6/24.
+ */
+public class RomUtil {
+
+ public static final String ROM_MIUI = "MIUI";
+ public static final String ROM_EMUI = "EMUI";
+ public static final String ROM_FLYME = "FLYME";
+ public static final String ROM_OPPO = "OPPO";
+ public static final String ROM_SMARTISAN = "SMARTISAN";
+ public static final String ROM_VIVO = "VIVO";
+ public static final String ROM_QIKU = "QIKU";
+
+ private static final String KEY_VERSION_MIUI = "ro.miui.ui.version.name";
+ private static final String KEY_VERSION_EMUI = "ro.build.version.emui";
+ private static final String KEY_VERSION_OPPO = "ro.build.version.opporom";
+ private static final String KEY_VERSION_SMARTISAN = "ro.smartisan.version";
+ private static final String KEY_VERSION_VIVO = "ro.vivo.os.version";
+
+ private static String sName;
+ private static String sVersion;
+
+ /**
+ * 华为
+ *
+ * @return boolean
+ */
+ public static boolean isEmui() {
+ return check(ROM_EMUI);
+ }
+
+ /**
+ * 小米
+ *
+ * @return boolean
+ */
+ public static boolean isMiui() {
+ return check(ROM_MIUI);
+ }
+
+ /**
+ * vivo
+ *
+ * @return boolean
+ */
+ public static boolean isVivo() {
+ return check(ROM_VIVO);
+ }
+
+ /**
+ * oppo
+ *
+ * @return boolean
+ */
+ public static boolean isOppo() {
+ return check(ROM_OPPO);
+ }
+
+ /**
+ * 魅族
+ *
+ * @return boolean
+ */
+ public static boolean isFlyme() {
+ return check(ROM_FLYME);
+ }
+
+ /**
+ * 360手机
+ *
+ * @return boolean
+ */
+ public static boolean is360() {
+ return check(ROM_QIKU) || check("360");
+ }
+
+ public static boolean isSmartisan() {
+ return check(ROM_SMARTISAN);
+ }
+
+ public static String getName() {
+ if (sName == null) {
+ check("");
+ }
+ return sName;
+ }
+
+ public static String getVersion() {
+ if (sVersion == null) {
+ check("");
+ }
+ return sVersion;
+ }
+
+ public static boolean check(String rom) {
+ if (sName != null) {
+ return sName.equals(rom);
+ }
+ if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_MIUI))) {
+ sName = ROM_MIUI;
+ } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_EMUI))) {
+ sName = ROM_EMUI;
+ } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_OPPO))) {
+ sName = ROM_OPPO;
+ } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_VIVO))) {
+ sName = ROM_VIVO;
+ } else if (!TextUtils.isEmpty(sVersion = getProp(KEY_VERSION_SMARTISAN))) {
+ sName = ROM_SMARTISAN;
+ } else {
+ sVersion = Build.DISPLAY;
+ if (sVersion.toUpperCase().contains(ROM_FLYME)) {
+ sName = ROM_FLYME;
+ } else {
+ sVersion = Build.UNKNOWN;
+ sName = Build.MANUFACTURER.toUpperCase();
+ }
+ }
+ return sName.equals(rom);
+ }
+
+ public static String getProp(String name) {
+ String line = null;
+ BufferedReader input = null;
+ try {
+ Process p = Runtime.getRuntime().exec("getprop " + name);
+ input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
+ line = input.readLine();
+ input.close();
+ } catch (IOException ex) {
+ return null;
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return line;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java b/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java
new file mode 100644
index 0000000..3cb335c
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/SelectorPopupWindow.java
@@ -0,0 +1,175 @@
+package com.wss.common.utils;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Build;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import com.wss.common.base.R;
+import com.wss.common.base.adapter.BaseListAdapter;
+import com.wss.common.base.adapter.listener.OnListItemClickListener;
+import com.wss.common.bean.SelectorData;
+
+import org.byteam.superadapter.SuperViewHolder;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+/**
+ * Describe:弹窗选择器
+ * Created by 吴天强 on 2020/4/21.
+ */
+public class SelectorPopupWindow extends PopupWindow {
+
+ private Context context;
+ private View parent;
+ private OnItemClickListener itemClickListener;
+ private PopupWindow.OnDismissListener dismissListener;
+ private List dataList = new ArrayList<>();
+ private String defaultChecked;
+
+ /**
+ * @param context context
+ * @param parent 显示位置父控件
+ */
+ public SelectorPopupWindow(Context context, View parent, List dataList) {
+ this.context = context;
+ this.parent = parent;
+ this.dataList.addAll(dataList);
+ }
+
+
+ /**
+ * 弹窗消失监听
+ *
+ * @param dismissListener 监听
+ * @return SelectorPopupWindow
+ */
+ public SelectorPopupWindow setDismissListener(PopupWindow.OnDismissListener dismissListener) {
+ this.dismissListener = dismissListener;
+ return this;
+ }
+
+ /**
+ * Item点击事件
+ *
+ * @param itemClickListener 事件
+ */
+ public SelectorPopupWindow setOnItemClickListener(OnItemClickListener itemClickListener) {
+ this.itemClickListener = itemClickListener;
+ return this;
+ }
+
+ /**
+ * 默认选择项
+ *
+ * @param defaultChecked 默认值
+ * @return SelectorPopupWindow
+ */
+ public SelectorPopupWindow setDefaultChecked(String defaultChecked) {
+ this.defaultChecked = defaultChecked;
+ return this;
+ }
+
+ public void show() {
+ initView(ViewGroup.LayoutParams.MATCH_PARENT);
+ }
+
+ /**
+ * 显示自定义宽度值
+ *
+ * @param value 宽度值
+ */
+ public void showMonthPopup(int value) {
+ initView(PxUtils.dp2px(value));
+ }
+
+ private void initView(int width) {
+ View childView = View.inflate(context, R.layout.pop_selector, null);
+ childView.findViewById(R.id.close).setOnClickListener(v -> dismiss());
+ initItems(childView);
+ setWidth(width);
+ setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
+ ColorDrawable dw = new ColorDrawable(0);
+ setBackgroundDrawable(dw);
+ setFocusable(true);
+ setOutsideTouchable(true);
+ setContentView(childView);
+ showAsDropDown(parent);
+ update();
+ setOnDismissListener(dismissListener);
+ }
+
+ private void initItems(@NotNull View childView) {
+ RecyclerView recyclerView = childView.findViewById(R.id.recycle_view);
+ recyclerView.setLayoutManager(new LinearLayoutManager(context));
+ recyclerView.setAdapter(new SelectorAdapter(context, dataList, R.layout.item_of_selector_pop,
+ (data, position) -> {
+ if (itemClickListener != null) {
+ itemClickListener.onItemClick(data);
+ }
+ dismiss();
+ }, defaultChecked));
+ }
+
+
+ @Override
+ public void showAsDropDown(View anchor) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ Rect visibleFrame = new Rect();
+ anchor.getGlobalVisibleRect(visibleFrame);
+ int height;
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O_MR1 && !RomUtil.isVivo()) {
+ //9.0
+ height = anchor.getResources().getDisplayMetrics().heightPixels - (visibleFrame.bottom - PxUtils.dp2px(30));
+ } else {
+ height = anchor.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom;
+ }
+ setHeight(height);
+ }
+ super.showAsDropDown(anchor);
+ }
+
+ /**
+ * 列表适配器
+ */
+ private static class SelectorAdapter extends BaseListAdapter {
+
+ private String defaultChecked;
+
+ SelectorAdapter(Context context, List mData, int layoutResId, OnListItemClickListener listener, String defaultChecked) {
+ super(context, mData, layoutResId, listener);
+ this.defaultChecked = defaultChecked;
+ }
+
+ @Override
+ public void onBindData(@NotNull SuperViewHolder holder, int viewType, int layoutPosition, @NotNull SelectorData data) {
+ TextView tvName = holder.findViewById(R.id.tv_name);
+ tvName.setText(data.getName());
+ tvName.setSelected(TextUtils.equals(defaultChecked, data.getName()));
+ }
+ }
+
+
+ /**
+ * Item点击事件监听
+ */
+ public interface OnItemClickListener {
+
+ /**
+ * Item点击回调
+ *
+ * @param data 选择数据
+ */
+ void onItemClick(SelectorData data);
+ }
+}
\ No newline at end of file
diff --git a/common_base/src/main/java/com/wss/common/utils/StringUtils.java b/common_base/src/main/java/com/wss/common/utils/StringUtils.java
deleted file mode 100644
index 55a80df..0000000
--- a/common_base/src/main/java/com/wss/common/utils/StringUtils.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.wss.common.utils;
-
-/**
- * Describe:字符串工具类
- * Created by 吴天强 on 2018/10/17.
- */
-
-public class StringUtils {
-
-
-}
diff --git a/common_base/src/main/java/com/wss/common/utils/SystemUtils.java b/common_base/src/main/java/com/wss/common/utils/SystemUtils.java
new file mode 100644
index 0000000..54c55a1
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/SystemUtils.java
@@ -0,0 +1,247 @@
+package com.wss.common.utils;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Build;
+import android.provider.Settings;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.security.MessageDigest;
+import java.util.Locale;
+import java.util.UUID;
+
+/**
+ * Describe:系统工具类
+ * Created by 吴天强 on 2019/5/5.
+ */
+public class SystemUtils {
+ /**
+ * 获取当前手机系统语言。
+ *
+ * @return 返回当前系统语言。例如:当前设置的是“中文-中国”,则返回“zh-CN”
+ */
+ @NotNull
+ public static String getSystemLanguage() {
+ return Locale.getDefault().getLanguage();
+ }
+
+ /**
+ * 获取当前系统上的语言列表(Locale列表)
+ *
+ * @return 语言列表
+ */
+ @NotNull
+ public static Locale[] getSystemLanguageList() {
+ return Locale.getAvailableLocales();
+ }
+
+ /**
+ * 获取当前手机系统版本号
+ *
+ * @return 系统版本号
+ */
+ @Contract(pure = true)
+ public static String getSystemVersion() {
+ return android.os.Build.VERSION.RELEASE;
+ }
+
+ /**
+ * 获取手机型号
+ *
+ * @return 手机型号
+ */
+ @Contract(pure = true)
+ public static String getSystemModel() {
+ return android.os.Build.MODEL;
+ }
+
+ /**
+ * 获取手机厂商
+ *
+ * @return 手机厂商
+ */
+ @Contract(pure = true)
+ public static String getDeviceBrand() {
+ return android.os.Build.BRAND;
+ }
+
+ /**
+ * 获取手机IMEI(需要“android.permission.READ_PHONE_STATE”权限)
+ *
+ * @return 手机IMEI
+ */
+ @Nullable
+ public static String getDeviceId(@NotNull Context context) {
+ StringBuilder sbDeviceId = new StringBuilder();
+
+ //获得设备默认IMEI(>=6.0 需要ReadPhoneState权限)
+ //获得AndroidId(无需权限)
+ String androidId = getAndroidId(context);
+ //获得设备序列号(无需权限)
+ String serial = getSerial();
+ //获得硬件uuid(根据硬件相关属性,生成uuid)(无需权限)
+ String uuid = getDeviceUUID().replace("-", "");
+ //追加androidId
+ if (androidId != null && androidId.length() > 0) {
+ sbDeviceId.append(androidId);
+ sbDeviceId.append("|");
+ }
+ //追加serial
+ if (serial != null && serial.length() > 0) {
+ sbDeviceId.append(serial);
+ sbDeviceId.append("|");
+ }
+ //追加硬件uuid
+ if (uuid.length() > 0) {
+ sbDeviceId.append(uuid);
+ }
+
+ //生成SHA1,统一DeviceId长度
+ if (sbDeviceId.length() > 0) {
+ try {
+ byte[] hash = getHashByString(sbDeviceId.toString());
+ String sha1 = bytesToHex(hash);
+ if (sha1.length() > 0) {
+ //返回最终的DeviceId
+ return sha1;
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ //如果以上硬件标识数据均无法获得,
+ //则DeviceId默认使用系统随机数,这样保证DeviceId不为空
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+
+ /**
+ * 获得设备的AndroidId
+ *
+ * @param context 上下文
+ * @return 设备的AndroidId
+ */
+ @SuppressLint("HardwareIds")
+ private static String getAndroidId(Context context) {
+ try {
+ return Settings.Secure.getString(context.getContentResolver(),
+ Settings.Secure.ANDROID_ID);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 获得设备序列号(如:WTK7N16923005607), 个别设备无法获取
+ *
+ * @return 设备序列号
+ */
+ private static String getSerial() {
+ try {
+ return Build.SERIAL;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 获得设备硬件uuid
+ * 使用硬件信息,计算出一个随机数
+ *
+ * @return 设备硬件uuid
+ */
+ @NotNull
+ private static String getDeviceUUID() {
+ try {
+ String dev = "3883756" +
+ Build.BOARD.length() % 10 +
+ Build.BRAND.length() % 10 +
+ Build.DEVICE.length() % 10 +
+ Build.HARDWARE.length() % 10 +
+ Build.ID.length() % 10 +
+ Build.MODEL.length() % 10 +
+ Build.PRODUCT.length() % 10 +
+ Build.SERIAL.length() % 10;
+ return new UUID(dev.hashCode(),
+ Build.SERIAL.hashCode()).toString();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return "";
+ }
+ }
+
+ /**
+ * 取SHA1
+ *
+ * @param data 数据
+ * @return 对应的hash值
+ */
+ private static byte[] getHashByString(String data) {
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
+ messageDigest.reset();
+ messageDigest.update(data.getBytes("UTF-8"));
+ return messageDigest.digest();
+ } catch (Exception e) {
+ return "".getBytes();
+ }
+ }
+
+ /**
+ * 转16进制字符串
+ *
+ * @param data 数据
+ * @return 16进制字符串
+ */
+ @NotNull
+ private static String bytesToHex(@NotNull byte[] data) {
+ StringBuilder sb = new StringBuilder();
+ String stmp;
+ for (byte datum : data) {
+ stmp = (Integer.toHexString(datum & 0xFF));
+ if (stmp.length() == 1) {
+ sb.append("0");
+ }
+ sb.append(stmp);
+ }
+ return sb.toString().toUpperCase(Locale.CHINA);
+ }
+
+
+ public static int getStatusBarHeight(@NotNull Context context) {
+ int result = 0;
+ int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
+ if (resourceId > 0) {
+ result = context.getResources().getDimensionPixelSize(resourceId);
+ }
+ return result;
+ }
+
+ public static int getScreenWidth(Context context) {
+ int screenWith = -1;
+ try {
+ screenWith = context.getResources().getDisplayMetrics().widthPixels;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return screenWith;
+ }
+
+ public static int getScreenHeight(Context context) {
+ int screenHeight = -1;
+ try {
+ screenHeight = context.getResources().getDisplayMetrics().heightPixels;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return screenHeight;
+ }
+
+
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java
index bf07c16..4ed6680 100644
--- a/common_base/src/main/java/com/wss/common/utils/ToastUtils.java
+++ b/common_base/src/main/java/com/wss/common/utils/ToastUtils.java
@@ -1,40 +1,382 @@
package com.wss.common.utils;
+import android.app.AppOpsManager;
+import android.app.Application;
+import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.GradientDrawable;
+import android.os.Build;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
import android.widget.Toast;
+import com.wss.common.utils.toast.BaseToast;
+import com.wss.common.utils.toast.IToastInterceptor;
+import com.wss.common.utils.toast.IToastStrategy;
+import com.wss.common.utils.toast.IToastStyle;
+import com.wss.common.utils.toast.SafeToast;
+import com.wss.common.utils.toast.SupportToast;
+import com.wss.common.utils.toast.ToastInterceptor;
+import com.wss.common.utils.toast.ToastStrategy;
+import com.wss.common.utils.toast.style.ToastBlackStyle;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
/**
* Describe:Toast
* Created by 吴天强 on 2017/11/2.
*/
+public final class ToastUtils {
+
+ private static IToastInterceptor sInterceptor;
+
+ private static IToastStrategy sStrategy;
+
+ private static Toast sToast;
+
+ /**
+ * 不允许外部实例化
+ */
+ private ToastUtils() {
+ }
+
+ /**
+ * 初始化 ToastUtils,在 Application 中初始化
+ *
+ * @param application 应用的上下文
+ */
+ public static void init(Application application) {
+ init(application, new ToastBlackStyle(application));
+ }
+
+ /**
+ * 初始化 ToastUtils 及样式
+ *
+ * @param application 应用的上下文
+ * @param style Toast样式
+ */
+ public static void init(Application application, IToastStyle style) {
+ checkNullPointer(application);
+ // 初始化 Toast 拦截器
+ if (sInterceptor == null) {
+ setToastInterceptor(new ToastInterceptor());
+ }
+
+ // 初始化 Toast 显示处理器
+ if (sStrategy == null) {
+ setToastStrategy(new ToastStrategy());
+ }
+
+ // 初始化吐司
+ if (areNotificationsEnabled(application)) {
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N_MR1) {
+ // 解决 Android 7.1 上主线程被阻塞后吐司会报错的问题
+ setToast(new SafeToast(application));
+ } else {
+ setToast(new BaseToast(application));
+ }
+ } else {
+ // 解决关闭通知栏权限后 Toast 不显示的问题
+ setToast(new SupportToast(application));
+ }
+
+ // 设置 Toast 视图
+ setView(createTextView(application, style));
+
+ // 设置 Toast 重心
+ setGravity(style.getGravity(), style.getXOffset(), style.getYOffset());
+ }
+
+ /**
+ * 显示一个对象的吐司
+ *
+ * @param object 对象
+ */
+ public static void show(Object object) {
+ show(object != null ? object.toString() : "null");
+ }
+
+ /**
+ * 显示一个吐司
+ *
+ * @param id 如果传入的是正确的 string id 就显示对应字符串
+ * 如果不是则显示一个整数的string
+ */
+ public static void show(int id) {
+ checkToastState();
+ try {
+ // 如果这是一个资源 id
+ show(getContext().getResources().getText(id));
+ } catch (Resources.NotFoundException ignored) {
+ // 如果这是一个 int 整数
+ show(String.valueOf(id));
+ }
+ }
+
+ /**
+ * 显示一个吐司
+ *
+ * @param id 资源 id
+ * @param args 参数集
+ */
+ public static void show(int id, Object... args) {
+ show(getContext().getResources().getString(id), args);
+ }
+
+ /**
+ * 显示一个吐司
+ *
+ * @param format 原字符串
+ * @param args 参数集
+ */
+ public static void show(String format, Object... args) {
+ show(String.format(format, args));
+ }
+
+ /**
+ * 显示一个吐司
+ *
+ * @param text 需要显示的文本
+ */
+ public static synchronized void show(CharSequence text) {
+ checkToastState();
+ if (sInterceptor.intercept(sToast, text)) {
+ return;
+ }
+ sStrategy.show(text);
+ }
+
-public class ToastUtils {
+ //***************************************兼容老的Toast的调用方法 start*************************************
- public static void showToast(Context context, int strings) {
- showToast(context, context.getString(strings));
+ /**
+ * 老的Toast调用方法
+ *
+ * @param context context
+ * @param text 显示的内容
+ */
+ public static void show(Context context, String text) {
+ show(text);
}
+ //***************************************兼容老的Toast的调用方法 end*************************************
- public static void showToast(Context context, String text) {
-// showToast(context, title, Gravity.BOTTOM);
- Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
+ /**
+ * 取消吐司的显示
+ */
+ public static synchronized void cancel() {
+ checkToastState();
+
+ sStrategy.cancel();
}
/**
- * 自定义显示Toast弹出提示框
+ * 设置吐司的位置
*
- * @param s s
- * @param gravity 弹出位置
+ * @param gravity 重心
+ * @param xOffset x轴偏移
+ * @param yOffset y轴偏移
+ */
+ private static void setGravity(int gravity, int xOffset, int yOffset) {
+ checkToastState();
+ gravity = Gravity.getAbsoluteGravity(gravity, sToast.getView().getResources().getConfiguration().getLayoutDirection());
+ sToast.setGravity(gravity, xOffset, yOffset);
+ }
+
+ /**
+ * 给当前Toast设置新的布局,具体实现可看{@link BaseToast#setView(View)}
+ */
+ public static void setView(int id) {
+ checkToastState();
+
+ setView(View.inflate(getContext(), id, null));
+ }
+
+ public static void setView(View view) {
+ checkToastState();
+
+ // 这个 View 不能为空
+ checkNullPointer(view);
+
+ // 当前必须用 Application 的上下文创建的 View,否则可能会导致内存泄露
+ Context context = view.getContext();
+ if (!(context instanceof Application)) {
+ throw new IllegalArgumentException("The view must be initialized using the context of the application");
+ }
+
+ // 如果吐司已经创建,就重新初始化吐司
+ if (sToast != null) {
+ // 取消原有吐司的显示
+ sToast.cancel();
+ sToast.setView(view);
+ }
+ }
+
+ /**
+ * 获取当前 Toast 的视图
+ */
+ @SuppressWarnings("unchecked")
+ public static V getView() {
+ checkToastState();
+
+ return (V) sToast.getView();
+ }
+
+ /**
+ * 初始化全局的Toast样式
+ *
+ * @param style 样式实现类,框架已经实现三种不同的样式
+ */
+ public static void initStyle(IToastStyle style) {
+ checkNullPointer(style);
+ // 如果吐司已经创建,就重新初始化吐司
+ if (sToast != null) {
+ // 取消原有吐司的显示
+ sToast.cancel();
+ sToast.setView(createTextView(getContext(), style));
+ sToast.setGravity(style.getGravity(), style.getXOffset(), style.getYOffset());
+ }
+ }
+
+ /**
+ * 设置当前Toast对象
+ */
+ public static void setToast(Toast toast) {
+ checkNullPointer(toast);
+ if (sToast != null && toast.getView() == null) {
+ // 移花接木
+ toast.setView(sToast.getView());
+ toast.setGravity(sToast.getGravity(), sToast.getXOffset(), sToast.getYOffset());
+ toast.setMargin(sToast.getHorizontalMargin(), sToast.getVerticalMargin());
+ }
+ sToast = toast;
+ if (sStrategy != null) {
+ sStrategy.bind(sToast);
+ }
+ }
+
+ /**
+ * 设置 Toast 显示策略
+ */
+ public static void setToastStrategy(IToastStrategy handler) {
+ checkNullPointer(handler);
+ sStrategy = handler;
+ if (sToast != null) {
+ sStrategy.bind(sToast);
+ }
+ }
+
+ /**
+ * 设置 Toast 拦截器(可以根据显示的内容决定是否拦截这个Toast)
+ * 场景:打印 Toast 内容日志、根据 Toast 内容是否包含敏感字来动态切换其他方式显示(这里可以使用我的另外一套框架 XToast)
+ */
+ public static void setToastInterceptor(IToastInterceptor interceptor) {
+ checkNullPointer(interceptor);
+ sInterceptor = interceptor;
+ }
+
+ /**
+ * 获取当前Toast对象
+ */
+ public static Toast getToast() {
+ return sToast;
+ }
+
+ /**
+ * 检查吐司状态,如果未初始化请先调用{@link com.wss.common.utils.ToastUtils#init(Application)}
+ */
+ private static void checkToastState() {
+ // 吐司工具类还没有被初始化,必须要先调用init方法进行初始化
+ if (sToast == null) {
+ throw new IllegalStateException("ToastUtils has not been initialized");
+ }
+ }
+
+ /**
+ * 检查对象是否为空
+ */
+ private static void checkNullPointer(Object object) {
+ if (object == null) {
+ throw new NullPointerException("are you ok?");
+ }
+ }
+
+ /**
+ * 生成默认的 TextView 对象
+ */
+ private static TextView createTextView(Context context, IToastStyle style) {
+
+ GradientDrawable drawable = new GradientDrawable();
+ // 设置背景色
+ drawable.setColor(style.getBackgroundColor());
+ // 设置圆角大小
+ drawable.setCornerRadius(style.getCornerRadius());
+
+ TextView textView = new TextView(context);
+ textView.setId(android.R.id.message);
+ textView.setTextColor(style.getTextColor());
+ textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getTextSize());
+
+ // 适配布局反方向
+ textView.setPaddingRelative(style.getPaddingStart(), style.getPaddingTop(), style.getPaddingEnd(), style.getPaddingBottom());
+
+ textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ // setBackground API 版本兼容
+ textView.setBackground(drawable);
+
+ // 设置 Z 轴阴影
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ textView.setZ(style.getZ());
+ }
+
+ // 设置最大显示行数
+ if (style.getMaxLines() > 0) {
+ textView.setMaxLines(style.getMaxLines());
+ }
+
+ return textView;
+ }
+
+ /**
+ * 获取上下文对象
+ */
+ private static Context getContext() {
+ checkToastState();
+ return sToast.getView().getContext();
+ }
+
+ /**
+ * 检查通知栏权限有没有开启
+ * 参考 SupportCompat 包中的方法: NotificationManagerCompat.from(context).areNotificationsEnabled();
*/
+ private static boolean areNotificationsEnabled(Context context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ return manager != null && manager.areNotificationsEnabled();
+ } else {
+ AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ ApplicationInfo appInfo = context.getApplicationInfo();
+ String packageName = context.getApplicationContext().getPackageName();
+ int uid = appInfo.uid;
- public static void showToast(Context context, CharSequence s, int gravity) {
-// Toast toast = new Toast(context);
-// View toastView = View.inflate(context, R.layout.toast, null);
-// toast.setView(toastView);
-// toast.setDuration(Toast.LENGTH_SHORT);
-// TextView textView = toastView.findViewById(R.id.tv_message);
-// textView.setText(s);
-// toast.setGravity(gravity, 0, 100);
-// toast.show();
+ try {
+ Class> appOpsClass = Class.forName(AppOpsManager.class.getName());
+ Method checkOpNoThrowMethod = appOpsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class);
+ Field opPostNotificationValue = appOpsClass.getDeclaredField("OP_POST_NOTIFICATION");
+ int value = Integer.parseInt(String.valueOf(opPostNotificationValue.get(Integer.class)));
+ return ((int) checkOpNoThrowMethod.invoke(appOps, value, uid, packageName) == AppOpsManager.MODE_ALLOWED);
+ } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException
+ | InvocationTargetException | IllegalAccessException | RuntimeException ignored) {
+ return true;
+ }
+ }
}
}
diff --git a/common_base/src/main/java/com/wss/common/utils/Utils.java b/common_base/src/main/java/com/wss/common/utils/Utils.java
index ad05281..63c460f 100644
--- a/common_base/src/main/java/com/wss/common/utils/Utils.java
+++ b/common_base/src/main/java/com/wss/common/utils/Utils.java
@@ -1,7 +1,18 @@
package com.wss.common.utils;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.graphics.drawable.GradientDrawable;
+import android.net.Uri;
+import android.widget.TextView;
+
+import com.wss.common.base.BaseApplication;
+
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
@@ -9,23 +20,23 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import androidx.annotation.NonNull;
+
/**
* Describe:工具类
* Created by 吴天强 on 2018/10/15.
*/
-
public class Utils {
-
/**
* 读取 asset下的文件
*
* @param context context
* @param fileName fileName
- * @return
+ * @return String
*/
- public static String getAssetFileData(Context context, String fileName) {
-
+ @NonNull
+ public static String getAssetFileData(@NotNull Context context, String fileName) {
StringBuilder stringBuilder = new StringBuilder();
try {
AssetManager assetManager = context.getAssets();
@@ -72,4 +83,122 @@ public static boolean isNumber(String str) {
return isNum.matches();
}
+ /**
+ * 判断是否为电话,只校验位数
+ *
+ * @param str str
+ * @return boolean
+ */
+ public static boolean isPhone(String str) {
+ return ValidUtils.isValid(str) && str.length() == 11;
+ }
+
+ /**
+ * 获取APP包名
+ *
+ * @return String
+ */
+ public static String getPackageName() {
+ return BaseApplication.i().getPackageName();
+ }
+
+ /**
+ * 获取APP 版本名称
+ *
+ * @return String
+ */
+ public static String getVersionName() {
+ PackageManager packageManager = BaseApplication.i().getPackageManager();
+ try {
+ PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
+ return packageInfo.versionName;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ /**
+ * 获取APP 版本号
+ *
+ * @return Integer
+ */
+ public static Integer getVersionCode() {
+ PackageManager packageManager = BaseApplication.i().getPackageManager();
+ try {
+ PackageInfo packageInfo = packageManager.getPackageInfo(
+ getPackageName(), 0);
+ return packageInfo.versionCode;
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return 0;
+ }
+
+ /**
+ * 设置TextView的背景色
+ *
+ * @param textView textView
+ * @param color 颜色
+ */
+ public static void setTextViewDrawable(@NotNull TextView textView, int color) {
+ setTextViewDrawable(textView, color, 4);
+ }
+
+ /**
+ * 设置TextView的背景色
+ *
+ * @param textView textView
+ * @param color 颜色
+ * @param radius 圆角角度
+ */
+ public static void setTextViewDrawable(@NotNull TextView textView, int color, float radius) {
+ GradientDrawable drawable = new GradientDrawable();
+ drawable.setCornerRadius(radius);
+ drawable.setColor(color);
+ textView.setBackground(drawable);
+ }
+
+ /**
+ * 跳转浏览器
+ */
+ public static void toSystemBrowser(@NonNull Context context, String url) {
+ //应用内下载失败 跳转浏览器下载
+ Intent intent = new Intent();
+ intent.setAction("android.intent.action.VIEW");
+ Uri contentUrl = Uri.parse(url);
+ intent.setData(contentUrl);
+ context.startActivity(intent);
+ }
+
+
+
+
+ /**
+ * 电话号码中间替换成*
+ *
+ * @param phone 原电话
+ * @return 替换后的电话
+ */
+ @Contract("_ -> param1")
+ public static String replacePhone(String phone) {
+ if (!isPhone(phone)) {
+ return phone;
+ }
+ String replace = phone.substring(3, 7);
+ return phone.replace(replace, "****");
+ }
+
+ /**
+ * 把等于null的字符串转成“”
+ *
+ * @param text 原字符串
+ * @return 转换后字符串
+ */
+ public static String checkText(String text) {
+ if (!ValidUtils.isValid(text)) {
+ return "";
+ }
+ return text;
+ }
}
diff --git a/common_base/src/main/java/com/wss/common/utils/ValidUtils.java b/common_base/src/main/java/com/wss/common/utils/ValidUtils.java
new file mode 100644
index 0000000..822401d
--- /dev/null
+++ b/common_base/src/main/java/com/wss/common/utils/ValidUtils.java
@@ -0,0 +1,39 @@
+package com.wss.common.utils;
+
+import android.text.TextUtils;
+
+import org.jetbrains.annotations.Contract;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * 对象空判断验证类
+ * Created by 吴天强 on 2017/12/3.
+ */
+public class ValidUtils {
+ @Contract(value = "null -> false", pure = true)
+ public static boolean isValid(Collection collection) {
+ return collection != null && !collection.isEmpty();
+ }
+
+ @Contract("null, _ -> false")
+ public static boolean isValid(Collection collection, int position) {
+ return collection != null && !collection.isEmpty() && collection.size() > position;
+ }
+
+ @Contract(value = "null -> false", pure = true)
+ public static boolean isValid(Map map) {
+ return map != null && !map.isEmpty();
+ }
+
+ @Contract("null -> false")
+ public static boolean isValid(String str) {
+ return !TextUtils.isEmpty(str);
+ }
+
+ @Contract(value = "null -> false; !null -> true", pure = true)
+ public static boolean isValid(Object obj) {
+ return obj != null;
+ }
+}
diff --git a/common_base/src/main/java/com/wss/common/utils/ZipUtils.java b/common_base/src/main/java/com/wss/common/utils/ZipUtils.java
deleted file mode 100644
index eafd00a..0000000
--- a/common_base/src/main/java/com/wss/common/utils/ZipUtils.java
+++ /dev/null
@@ -1,390 +0,0 @@
-package com.wss.common.utils;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Java utils 实现的Zip工具
- *
- * @author miaowei
- */
-public class ZipUtils {
-
- private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte
-
- /**
- * 批量压缩文件(夹)
- *
- * @param resFileList 要压缩的文件(夹)列表
- * @param zipFile 生成的压缩文件
- * @throws IOException 当压缩过程出错时抛出
- */
- public static void zipFiles(Collection resFileList, File zipFile) throws IOException {
- if (resFileList != null && zipFile != null) {
- ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE));
- for (File resFile : resFileList) {
- zipFile(resFile, zipout, "");
- }
- zipout.close();
- }
- }
-
- /**
- * 批量压缩文件(夹)
- *
- * @param resFileList 要压缩的文件(夹)列表
- * @param zipFile 生成的压缩文件
- * @param comment 压缩文件的注释
- * @throws IOException 当压缩过程出错时抛出
- */
- public static void zipFiles(Collection resFileList, File zipFile, String comment) throws IOException {
- ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile), BUFF_SIZE));
- for (File resFile : resFileList) {
- zipFile(resFile, zipout, "");
- }
- zipout.setComment(comment);
- zipout.close();
- }
-
- /**
- * 解压缩一个文件
- *
- * @param zipFile 压缩文件
- * @param folderPath 解压缩的目标目录
- * @throws IOException 当解压缩过程出错时抛出
- */
- public static void upZipFile(File zipFile, String folderPath) throws IOException {
- File desDir = new File(folderPath);
- if (!desDir.exists()) {
- desDir.mkdirs();
- }
- ZipFile zf = new ZipFile(zipFile);
- for (Enumeration> entries = zf.entries(); entries.hasMoreElements(); ) {
- ZipEntry entry = ((ZipEntry) entries.nextElement());
- if (entry.isDirectory()) {
-
- continue;
- }
- InputStream in = zf.getInputStream(entry);
- String str = folderPath + File.separator + entry.getName();
- str = new String(str.getBytes(), "utf-8");
- File desFile = new File(str);
- if (!desFile.exists()) {
- File fileParentDir = desFile.getParentFile();
- if (!fileParentDir.exists()) {
- fileParentDir.mkdirs();
- }
- desFile.createNewFile();
- }
- OutputStream out = new FileOutputStream(desFile);
- byte buffer[] = new byte[BUFF_SIZE];
- int realLength;
- while ((realLength = in.read(buffer)) > 0) {
- out.write(buffer, 0, realLength);
- }
- in.close();
- out.close();
- }
- }
-
- /**
- * 解压文件名包含传入文字的文件
- *
- * @param zipFile 压缩文件
- * @param folderPath 目标文件夹
- * @param nameContains 传入的文件匹配名
- * @throws ZipException 压缩格式有误时抛出
- * @throws IOException IO错误时抛出
- */
- public static ArrayList upZipSelectedFile(File zipFile, String folderPath, String nameContains) throws IOException {
- ArrayList fileList = new ArrayList();
-
- File desDir = new File(folderPath);
- if (!desDir.exists()) {
- desDir.mkdir();
- }
-
- ZipFile zf = new ZipFile(zipFile);
- for (Enumeration> entries = zf.entries(); entries.hasMoreElements(); ) {
- ZipEntry entry = ((ZipEntry) entries.nextElement());
- if (entry.getName().contains(nameContains)) {
- InputStream in = zf.getInputStream(entry);
- String str = folderPath + File.separator + entry.getName();
- str = new String(str.getBytes("utf-8"), "gbk");
- // str.getBytes("GB2312"),"8859_1" 输出
- // str.getBytes("8859_1"),"GB2312" 输入
- File desFile = new File(str);
- if (!desFile.exists()) {
- File fileParentDir = desFile.getParentFile();
- if (!fileParentDir.exists()) {
- fileParentDir.mkdirs();
- }
- desFile.createNewFile();
- }
- OutputStream out = new FileOutputStream(desFile);
- byte buffer[] = new byte[BUFF_SIZE];
- int realLength;
- while ((realLength = in.read(buffer)) > 0) {
- out.write(buffer, 0, realLength);
- }
- in.close();
- out.close();
- fileList.add(desFile);
- }
- }
- return fileList;
- }
-
- /**
- * 获得压缩文件内文件列表
- *
- * @param zipFile 压缩文件
- * @return 压缩文件内文件名称
- * @throws ZipException 压缩文件格式有误时抛出
- * @throws IOException 当解压缩过程出错时抛出
- */
- public static ArrayList