├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── dictionaries
│ └── xhinliang.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── Api.md
├── LICENSE
├── README.md
├── app
├── .gitignore
├── app-release.apk
├── build.gradle
├── libs
│ ├── armeabi
│ │ └── libbspatch.so
│ └── umeng-update-v2.6.0.1.jar
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wecan
│ │ └── xhin
│ │ └── studio
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wecan
│ │ │ └── xhin
│ │ │ └── studio
│ │ │ ├── App.java
│ │ │ ├── activity
│ │ │ ├── AboutActivity.java
│ │ │ ├── LoginActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── MyDetailsActivity.java
│ │ │ ├── PictureActivity.java
│ │ │ ├── RegisterActivity.java
│ │ │ ├── TestActivity.java
│ │ │ └── UserDetailsActivity.java
│ │ │ ├── adapter
│ │ │ ├── LibrariesAdapter.java
│ │ │ ├── SimpleAdapter.java
│ │ │ └── UsersAdapter.java
│ │ │ ├── api
│ │ │ └── Api.java
│ │ │ ├── bean
│ │ │ ├── GitRepository.java
│ │ │ ├── Simple.java
│ │ │ ├── common
│ │ │ │ └── User.java
│ │ │ ├── down
│ │ │ │ ├── BaseData.java
│ │ │ │ └── UsersData.java
│ │ │ └── up
│ │ │ │ ├── RegisterBody.java
│ │ │ │ └── SignBody.java
│ │ │ ├── fragment
│ │ │ ├── AllUserFragment.java
│ │ │ ├── BooksFragment.java
│ │ │ ├── RxBindingFragment.java
│ │ │ ├── SignedUserFragment.java
│ │ │ └── UsersFragment.java
│ │ │ ├── net
│ │ │ └── OkHttpGlideModule.java
│ │ │ └── reactivex
│ │ │ └── BindingRecyclerView.java
│ └── res
│ │ ├── drawable-hdpi
│ │ ├── defimgs.png
│ │ ├── header.jpg
│ │ ├── umeng_update_btn_check_off_focused_holo_light.png
│ │ ├── umeng_update_btn_check_off_holo_light.png
│ │ ├── umeng_update_btn_check_off_pressed_holo_light.png
│ │ ├── umeng_update_btn_check_on_focused_holo_light.png
│ │ ├── umeng_update_btn_check_on_holo_light.png
│ │ ├── umeng_update_btn_check_on_pressed_holo_light.png
│ │ ├── umeng_update_close_bg_normal.png
│ │ └── umeng_update_close_bg_tap.png
│ │ ├── drawable-xxxhdpi
│ │ ├── ic_sign.png
│ │ └── ic_unsign.png
│ │ ├── drawable
│ │ ├── bg_material_button_lite_blue.xml
│ │ ├── ic_menu_camera.xml
│ │ ├── ic_menu_gallery.xml
│ │ ├── ic_menu_manage.xml
│ │ ├── ic_menu_send.xml
│ │ ├── ic_menu_share.xml
│ │ ├── ic_menu_slideshow.xml
│ │ ├── tb_munion_icon.xml
│ │ ├── tb_munion_item_selector.xml
│ │ ├── umeng_common_gradient_green.xml
│ │ ├── umeng_common_gradient_orange.xml
│ │ ├── umeng_common_gradient_red.xml
│ │ ├── umeng_update_button_cancel_bg_focused.xml
│ │ ├── umeng_update_button_cancel_bg_normal.xml
│ │ ├── umeng_update_button_cancel_bg_selector.xml
│ │ ├── umeng_update_button_cancel_bg_tap.xml
│ │ ├── umeng_update_button_check_selector.xml
│ │ ├── umeng_update_button_close_bg_selector.xml
│ │ ├── umeng_update_button_ok_bg_focused.xml
│ │ ├── umeng_update_button_ok_bg_normal.xml
│ │ ├── umeng_update_button_ok_bg_selector.xml
│ │ ├── umeng_update_button_ok_bg_tap.xml
│ │ ├── umeng_update_dialog_bg.xml
│ │ ├── umeng_update_title_bg.xml
│ │ └── umeng_update_wifi_disable.png
│ │ ├── layout-v9
│ │ └── umeng_common_download_notification.xml
│ │ ├── layout
│ │ ├── activity_about.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ ├── activity_picture.xml
│ │ ├── activity_register.xml
│ │ ├── activity_user_details.xml
│ │ ├── fragment_users.xml
│ │ ├── include_nav_header_main.xml
│ │ ├── recycler_item_header.xml
│ │ ├── recycler_item_library.xml
│ │ ├── recycler_item_simple.xml
│ │ ├── recycler_item_user.xml
│ │ ├── tb_munion_aditem.xml
│ │ ├── umeng_common_download_notification.xml
│ │ └── umeng_update_dialog.xml
│ │ ├── menu
│ │ ├── activity_main_drawer.xml
│ │ ├── main.xml
│ │ └── menu_scrolling.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxhdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xxxhdpi
│ │ └── ic_launcher.png
│ │ ├── values-en-rUs
│ │ └── arrays.xml
│ │ ├── values-en
│ │ ├── strings.xml
│ │ ├── tb_munion_strings.xml
│ │ ├── umeng_common_strings.xml
│ │ └── umeng_update_string.xml
│ │ ├── values-v19
│ │ └── styles.xml
│ │ ├── values-v21
│ │ └── styles.xml
│ │ ├── values-zh-rCn
│ │ └── arrays.xml
│ │ ├── values-zh
│ │ ├── strings.xml
│ │ ├── tb_munion_strings.xml
│ │ ├── umeng_common_strings.xml
│ │ └── umeng_update_string.xml
│ │ └── values
│ │ ├── arrays.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── drawables.xml
│ │ ├── strings.xml
│ │ ├── styles.xml
│ │ ├── tb_munion_strings.xml
│ │ ├── umeng_common_strings.xml
│ │ └── umeng_update_string.xml
│ └── test
│ └── java
│ └── com
│ └── wecan
│ └── xhin
│ └── studio
│ └── ExampleUnitTest.java
├── baselib
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wecan
│ │ └── xhin
│ │ └── baselib
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── wecan
│ │ │ └── xhin
│ │ │ └── baselib
│ │ │ ├── activity
│ │ │ ├── BaseActivity.java
│ │ │ └── SingleFragmentActivity.java
│ │ │ ├── fragment
│ │ │ └── BaseFragment.java
│ │ │ ├── net
│ │ │ └── LoggingInterceptor.java
│ │ │ ├── rx
│ │ │ ├── RxEndlessRecyclerView.java
│ │ │ └── RxNetworking.java
│ │ │ ├── util
│ │ │ └── PreferenceHelper.java
│ │ │ └── widget
│ │ │ ├── StatusBarHolderView.java
│ │ │ └── VideoImageView.java
│ └── res
│ │ ├── layout
│ │ ├── activity_single_fragment.xml
│ │ └── include_toolbar.xml
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── wecan
│ └── xhin
│ └── baselib
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── wef.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Studio
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/dictionaries/xhinliang.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | addplease
5 | appid
6 | attacher
7 | balysv
8 | donglua
9 | imgurl
10 | liang
11 | mailto
12 | mantou
13 | nineoldandroids
14 | okhttp
15 | oxoooo
16 | photopicker
17 | pojo
18 | trello
19 | unsign
20 | wecanstudio
21 | xidian
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/misc.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 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Api.md:
--------------------------------------------------------------------------------
1 | # # 接口规范
2 |
3 | 需要实现基于 HTTP/JSON 的 RESTful API,至少包含以下接口:
4 |
5 | 基地址 http://121.42.209.19/RestfulApi/index.php/
6 |
7 | 1. 登录
8 | 2. 注册
9 | 3. 修改用户信息
10 | 4. 用户签到
11 | 5. 用户签退
12 | 6. 获取所有用户信息
13 | 7. 获取已签到用户信息
14 | 8. 增加邀请码信息
15 | 9. 获取所有邀请码信息
16 |
17 |
18 |
19 |
20 | 如果需要传参的接口,传过来的请求体 json 格式有误或验证结果错误。则返回错误状态
21 |
22 | ```
23 | {
24 | "status": "-1"
25 | }
26 | ```
27 |
28 | ## 登录
29 |
30 | `GET /user`
31 |
32 | ##### 请求体
33 |
34 | 参数名 | 类型 | 描述
35 | ---|---|---
36 | name | string | 用户名
37 | phone | string | 密码
38 |
39 | #####请求示例
40 |
41 | ```
42 | GET /api/users?name=xxx&phone=xxx
43 | ```
44 |
45 | ##### 响应示例
46 |
47 | ```
48 | 200 OK
49 | {
50 | "id": "10",
51 | "name": "wer123",
52 | "sex": "1",
53 | "group_name": "2",
54 | "phone": "121",
55 | "imgurl": "www.123456.com",
56 | "position": "3",
57 | "sign_date": "2015-11-20 15:52:31",
58 | "status": "0"
59 | }
60 | ```
61 |
62 | ##### 异常示例
63 |
64 | 用户名不存在或者密码错误:
65 |
66 | ```
67 | 403 Forbidden
68 | {
69 | "status": -1,
70 | "message": "用户名密码错误"
71 | }
72 | ```
73 |
74 |
75 | ## 注册
76 |
77 | `POST /api/users`
78 |
79 | #### 请求体
80 |
81 | 参数名 | 类型 | 描述
82 | ---|---|---
83 | name | string | 用户名
84 | sex | int | 性别
85 | group_name | int | 小组类别
86 | imgurl | string | 头像
87 | phone | string | 电话号码
88 | position | int | 职位
89 | code | string | 邀请码
90 |
91 |
92 |
93 | #### 请求示例
94 |
95 | ```
96 | POST /api/users
97 |
98 | {"name" : "wer12312", "sex" : 1, "group_name" : 2, "imgurl" : "www.123456.com", "phone" : "121", "position" : 3, "code" : "123"}
99 |
100 |
101 | ```
102 |
103 | #### 响应示例
104 |
105 | ```
106 | 200 OK
107 | {
108 | "status": 1
109 | }
110 | ```
111 |
112 | #### 异常示例
113 | 邀请码不存在或已被注册
114 |
115 | ```
116 | 403 Forbidden
117 | {
118 | "status": -1,
119 | "message": "邀请码不存在"
120 | }
121 | ```
122 |
123 | 用户名重复
124 |
125 | ```
126 | {
127 | "status": -1,
128 | "message": "用户名重复"
129 | }
130 | ```
131 |
132 |
133 |
134 | ## 修改用户信息
135 |
136 |
137 | #### 请求体
138 |
139 | 参数名 | 类型 | 描述
140 | ---|---|---
141 | name | string | 用户名
142 | sex | int | 性别
143 | group_name | int | 小组类别
144 | imgurl | string | 头像
145 | phone | string | 电话号码
146 | position | int | 职位
147 |
148 |
149 |
150 | #### 请求示例
151 |
152 | ```
153 | PUT api/users
154 | {"name" : "wer123", "sex" : 1, "group_name" : 2, "imgurl" : "www.123456123.com", "phone" : "121", "position" : 3}
155 | ```
156 |
157 |
158 | #### 响应示例
159 |
160 | ```
161 | 200 OK
162 | {
163 | "id": "10",
164 | "name": "wer123",
165 | "sex": "1",
166 | "group_name": 2,
167 | "phone": "121",
168 | "imgurl": "www.123456123.com",
169 | "position": 3,
170 | "sign_date": "2015-11-20 15:52:31",
171 | "status": "0"
172 | }
173 | ```
174 |
175 | #### 异常示例
176 | ```
177 | 403 Forbidden
178 | {
179 | "status": -1,
180 | "message": "用户名信息错误"
181 | }
182 | ```
183 |
184 |
185 | ####说明
186 | ```
187 | name与sex无法更改
188 | ```
189 |
190 |
191 | ## 用户签到
192 |
193 | `POST /api/sign`
194 |
195 | ##### 请求体
196 |
197 | 参数名 | 类型 | 描述
198 | ---|---|---
199 | name | string | 用户名
200 |
201 | #### 请求示例
202 |
203 | ```
204 | POST /api/sign
205 | {
206 | "name" : "wer123"
207 | }
208 | ```
209 |
210 | #### 响应示例
211 |
212 | 签到成功
213 |
214 | ```
215 | 200 OK
216 | {
217 | "status":"1"
218 | }
219 | ```
220 |
221 |
222 | #### 异常示例
223 |
224 | ```
225 | 403
226 | {
227 | "status": -1,
228 | "message": "用户还没有下线"
229 | }
230 | ```
231 |
232 |
233 |
234 |
235 | ## 用户签退
236 |
237 | `DELETE /api/sign`
238 |
239 | ##### 请求体
240 |
241 | 参数名 | 类型 | 描述
242 | ---|---|---
243 | name | string | 类型名称
244 |
245 | #### 请求示例
246 |
247 | ```
248 | DELETE /api/sign?name=xxx
249 | ```
250 |
251 | #### 响应示例
252 |
253 | ```
254 | 200 OK
255 | {
256 | "status": 1
257 | }
258 | ```
259 |
260 | #### 异常示例
261 |
262 | 用户名没有签到
263 |
264 | ```
265 | 403
266 | {
267 | "status": -1,
268 | "message": "用户还没有签到"
269 | }
270 | ```
271 |
272 |
273 |
274 |
275 | ## 获取所有用户信息
276 | `GET /api/message_all`
277 |
278 |
279 |
280 | #### 请求示例
281 |
282 | ```
283 | GET /api/message_all
284 | ```
285 |
286 | #### 响应示例
287 |
288 | ```
289 | 200 OK
290 | {
291 | "status": 1,
292 | "data": [
293 | {
294 | "id": "13",
295 | "name": "wer12312",
296 | "sex": "1",
297 | "group_name": "2",
298 | "phone": "121",
299 | "imgurl": "www.123456.com",
300 | "position": "3",
301 | "sign_date": "2015-11-20 18:45:20",
302 | "status": "0"
303 | },
304 | {
305 | "id": "10",
306 | "name": "wer123",
307 | "sex": "1",
308 | "group_name": "2",
309 | "phone": "121",
310 | "imgurl": "www.123456123.com",
311 | "position": "3",
312 | "sign_date": "2015-11-20 15:52:31",
313 | "status": "0"
314 | },
315 | {
316 | "id": "12",
317 | "name": "wer1231231",
318 | "sex": "1",
319 | "group_name": "1",
320 | "phone": "123",
321 | "imgurl": "www.123.com",
322 | "position": "1",
323 | "sign_date": "2015-11-20 15:55:01",
324 | "status": "0"
325 | }
326 | ]
327 | }
328 | ```
329 |
330 |
331 |
332 | ## 获取已签到用户信息
333 | `GET /api/message`
334 |
335 |
336 |
337 | #### 响应示例
338 |
339 | ```
340 | 200 OK
341 | {
342 | "status": 1,
343 | "data": [
344 | {
345 | "id": "4",
346 | "name": "wer",
347 | "sex": "1",
348 | "group_name": "1",
349 | "phone": "123",
350 | "imgurl": "www.123.com",
351 | "position": "1",
352 | "sign_date": "2015-11-20 15:07:47",
353 | "status": "1"
354 | }
355 | ]
356 | }
357 | ```
358 |
359 |
360 |
361 | ## 增加邀请码信息
362 |
363 | `GET /api/addplease/(num)`
364 |
365 |
366 |
367 | #### 请求示例
368 |
369 | ```
370 | GET /api/addplease/(num)
371 |
372 | ```
373 |
374 | #### 响应示例
375 |
376 | ```
377 | 200 OK
378 | {
379 | "status": 1
380 | }
381 | ```
382 |
383 |
384 |
385 |
386 | ## 获取所有邀请码
387 |
388 | `GET /api/getplease`
389 |
390 |
391 |
392 | #### 请求示例
393 |
394 | ```
395 | GET /api/getplease
396 |
397 | ```
398 |
399 | #### 响应示例
400 |
401 | ```
402 | 200 OK
403 | {
404 | "status": 1,
405 | "data": [
406 | {
407 | "id": "1",
408 | "num": "123",
409 | "status": "1"
410 | },
411 | {
412 | "id": "2",
413 | "num": "974c5743-3f6a-6dd5-f24f-f3e05bd3031d",
414 | "status": "1"
415 | },
416 | {
417 | "id": "3",
418 | "num": "296d19ad-d6b1-fa6e-b8d3-0a6abb303257",
419 | "status": "1"
420 | },
421 | {
422 | "id": "4",
423 | "num": "8a43cfa6-30ee-5c2c-fb6a-1dd14dc5650b",
424 | "status": "1"
425 | }
426 | ]
427 | }
428 | ```
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Studio
2 | 微客工作室 for Android.
3 |
4 | ## Thanks
5 | - [OkHttp](https://square.github.io/okhttp)
6 | - [Retrofit](https://square.github.io/retrofit)
7 | - [Gson](https://github.com/google/gson)
8 | - [RxJava](https://github.com/ReactiveX/RxJava)
9 | - [RxAndroid](https://github.com/ReactiveX/RxAndroid)
10 | - [RxBinding](https://github.com/JakeWharton/RxBinding)
11 | - [NineOldAndroids](https://github.com/JakeWharton/NineOldAndroids)
12 | - [RxLifecycle](https://github.com/trello/RxLifecycle)
13 | - [mr-mantou-android](https://github.com/oxoooo/mr-mantou-android)
14 | - [Meizhi](https://github.com/drakeet/Meizhi)
15 | - [PhotoPicker](https://github.com/donglua/PhotoPicker)
16 | - [material-ripple](https://github.com/balysv/material-ripple)
17 |
18 | ## License
19 |
20 | Copyright 2015 XhinLiang
21 |
22 | Licensed under the Apache License, Version 2.0 (the "License");
23 | you may not use this file except in compliance with the License.
24 | You may obtain a copy of the License at
25 |
26 | http://www.apache.org/licenses/LICENSE-2.0
27 |
28 | Unless required by applicable law or agreed to in writing, software
29 | distributed under the License is distributed on an "AS IS" BASIS,
30 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 | See the License for the specific language governing permissions and
32 | limitations under the License.
33 |
34 |
35 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/app-release.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/app-release.apk
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'com.android.databinding'
3 |
4 | android {
5 | compileSdkVersion 23
6 | buildToolsVersion "23.0.2"
7 |
8 | //为了解决部分第三方库重复打包了META-INF的问题
9 | packagingOptions {
10 | exclude 'META-INF/LICENSE.txt'
11 | exclude 'META-INF/NOTICE.txt'
12 | }
13 |
14 | lintOptions {
15 | abortOnError false
16 | }
17 |
18 | defaultConfig {
19 | applicationId "com.wecan.xhin.studio"
20 | minSdkVersion 16
21 | targetSdkVersion 23
22 | versionCode 8
23 | versionName "1.0.2"
24 | }
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 | }
32 |
33 | dependencies {
34 | compile fileTree(include: ['*.jar'], dir: 'libs')
35 | testCompile 'junit:junit:4.12'
36 | compile project(':baselib')
37 | compile 'cn.leancloud.android:avoscloud-sdk:v3.8.1'
38 | }
39 |
--------------------------------------------------------------------------------
/app/libs/armeabi/libbspatch.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/libs/armeabi/libbspatch.so
--------------------------------------------------------------------------------
/app/libs/umeng-update-v2.6.0.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/XhinLiang/Studio/656a82dde75ae8bb6d477d3e976cd2211e3cbfc6/app/libs/umeng-update-v2.6.0.1.jar
--------------------------------------------------------------------------------
/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 /opt/android-sdk-linux/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/androidTest/java/com/wecan/xhin/studio/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.wecan.xhin.studio;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
43 |
44 |
47 |
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
71 |
72 |
75 |
76 |
79 |
80 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wecan/xhin/studio/App.java:
--------------------------------------------------------------------------------
1 |
2 | package com.wecan.xhin.studio;
3 |
4 | import android.app.Application;
5 | import android.content.Context;
6 |
7 | import com.avos.avoscloud.AVOSCloud;
8 | import com.google.gson.FieldNamingPolicy;
9 | import com.google.gson.Gson;
10 | import com.google.gson.GsonBuilder;
11 | import com.squareup.okhttp.Interceptor;
12 | import com.squareup.okhttp.OkHttpClient;
13 | import com.squareup.okhttp.Response;
14 | import com.wecan.xhin.baselib.net.LoggingInterceptor;
15 | import com.wecan.xhin.studio.api.Api;
16 |
17 | import java.io.IOException;
18 | import java.util.HashMap;
19 |
20 | import retrofit.GsonConverterFactory;
21 | import retrofit.Retrofit;
22 | import retrofit.RxJavaCallAdapterFactory;
23 |
24 | public class App extends Application {
25 |
26 |
27 | public static final String VALUE_AVOS_APPID = "AkVsXJ4RoWq1juPauOHe1OW5";
28 | public static final String VALUE_AVOS_APPKEY = "gFICBkjJSxlI5fHnvNyB7Lfj";
29 |
30 | public static final String KEY_PREFERENCE_USER = "user";
31 | public static final String KEY_PREFERENCE_PHONE = "phone";
32 | public static final String KEY_BUILD_VERSION = "build_version";
33 | public static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
34 |
35 | private final HashMap apis = new HashMap<>();
36 |
37 | private Retrofit retrofit;
38 |
39 | //返回当前单例的静态方法,判断是否是当前的App调用
40 | public static App from(Context context) {
41 | Context application = context.getApplicationContext();
42 | if (application instanceof App)
43 | return (App) application;
44 | throw new IllegalArgumentException("Context must be from Studio");
45 | }
46 |
47 |
48 | @Override
49 | public void onCreate() {
50 | super.onCreate();
51 |
52 | AVOSCloud.initialize(this, VALUE_AVOS_APPID, VALUE_AVOS_APPKEY);
53 | OkHttpClient okHttpClient = new OkHttpClient();
54 | //OKHttp的使用
55 | okHttpClient.networkInterceptors().add(new Interceptor() {
56 | @Override
57 | public Response intercept(Chain chain) throws IOException {
58 | return chain.proceed(chain.request().newBuilder()
59 | .header(KEY_BUILD_VERSION, BuildConfig.VERSION_NAME)
60 | .build());
61 | }
62 | });
63 |
64 | if (BuildConfig.DEBUG) {
65 | okHttpClient.networkInterceptors().add(new LoggingInterceptor());
66 | }
67 |
68 | //初始化Gson
69 | Gson gson = new GsonBuilder()
70 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
71 | .setDateFormat(DATE_FORMAT_PATTERN)
72 | .create();
73 |
74 |
75 | //初始化Retrofit
76 | retrofit = new Retrofit.Builder()
77 | .client(okHttpClient)
78 | .addConverterFactory(GsonConverterFactory.create(gson))
79 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
80 | .baseUrl(Api.BASE_URL)
81 | .build();
82 | }
83 |
84 | //返回Retrofit的API
85 | public T createApi(Class service) {
86 | if (!apis.containsKey(service)) {
87 | T instance = retrofit.create(service);
88 | apis.put(service, instance);
89 | }
90 | //noinspection unchecked
91 | return (T) apis.get(service);
92 | }
93 |
94 | public OkHttpClient getHttpClient() {
95 | return retrofit.client();
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wecan/xhin/studio/activity/AboutActivity.java:
--------------------------------------------------------------------------------
1 | package com.wecan.xhin.studio.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.DialogInterface;
5 | import android.content.Intent;
6 | import android.content.pm.ResolveInfo;
7 | import android.databinding.DataBindingUtil;
8 | import android.net.Uri;
9 | import android.os.Bundle;
10 | import android.support.v7.app.AlertDialog;
11 | import android.widget.EditText;
12 |
13 | import com.jakewharton.rxbinding.view.RxView;
14 | import com.jakewharton.rxbinding.view.ViewClickEvent;
15 | import com.wecan.xhin.baselib.activity.BaseActivity;
16 | import com.wecan.xhin.baselib.rx.RxNetworking;
17 | import com.wecan.xhin.studio.App;
18 | import com.wecan.xhin.studio.R;
19 | import com.wecan.xhin.studio.adapter.LibrariesAdapter;
20 | import com.wecan.xhin.studio.api.Api;
21 | import com.wecan.xhin.studio.bean.GitRepository;
22 | import com.wecan.xhin.studio.bean.down.BaseData;
23 | import com.wecan.xhin.studio.databinding.ActivityAboutBinding;
24 |
25 | import java.util.LinkedList;
26 | import java.util.List;
27 |
28 | import rx.Observable;
29 | import rx.android.schedulers.AndroidSchedulers;
30 | import rx.functions.Action1;
31 | import rx.functions.Func0;
32 | import rx.functions.Func1;
33 | import rx.schedulers.Schedulers;
34 |
35 | /**
36 | * Created by xhinliang on 15-11-23.
37 | * xhinliang@gmail.com
38 | */
39 | public class AboutActivity extends BaseActivity implements LibrariesAdapter.Listener {
40 |
41 | private List libraries = new LinkedList<>();
42 | private Api api;
43 | private Observable.Transformer networkingIndicator;
44 |
45 | @Override
46 | protected void onCreate(Bundle savedInstanceState) {
47 | super.onCreate(savedInstanceState);
48 | ActivityAboutBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_about);
49 | setSupportActionBar(binding.toolbar);
50 | setHasHomeButton();
51 |
52 | setRxClick(binding.fab)
53 | .subscribe(new Action1() {
54 | @Override
55 | public void call(ViewClickEvent viewClickEvent) {
56 | composeEmail(getString(R.string.author_email));
57 | }
58 | });
59 |
60 | RxView.clickEvents(binding.toolbar)
61 | .elementAt(5)
62 | .compose(this.bindToLifecycle())
63 | .subscribe(new Action1() {
64 | @Override
65 | public void call(ViewClickEvent viewClickEvent) {
66 | addCode();
67 | }
68 | });
69 |
70 | setupRecyclerView(binding);
71 | initData();
72 | }
73 |
74 | private void initData() {
75 | api = App.from(this).createApi(Api.class);
76 | ProgressDialog pd = new ProgressDialog(this);
77 | networkingIndicator = RxNetworking.bindConnecting(pd);
78 | }
79 |
80 | private void addCodeToServer(final String code) {
81 | Observable
82 | .defer(new Func0>() {
83 | @Override
84 | public Observable call() {
85 | return api.addCode(code);
86 | }
87 | })
88 | .subscribeOn(Schedulers.io())
89 | .observeOn(AndroidSchedulers.mainThread())
90 | .compose(networkingIndicator)
91 | .compose(AboutActivity.this.bindToLifecycle())
92 | .subscribe(new Action1() {
93 | @Override
94 | public void call(BaseData baseData) {
95 | showSimpleDialog(R.string.add_code_result, R.string.succeed);
96 | }
97 | }, new Action1() {
98 | @Override
99 | public void call(Throwable throwable) {
100 | showSimpleDialog(R.string.add_code_result, R.string.fail);
101 | }
102 | });
103 | }
104 |
105 | private void addCode() {
106 | final EditText editText = new EditText(this);
107 | editText.setHint(R.string.add_code);
108 | new AlertDialog.Builder(this)
109 | .setTitle(R.string.add_code)
110 | .setView(editText)
111 | .setPositiveButton(R.string.confirm, new DialogInterface.OnClickListener() {
112 | @Override
113 | public void onClick(DialogInterface dialog, int which) {
114 | addCodeToServer(editText.getText().toString());
115 | }
116 | })
117 | .create()
118 | .show();
119 | }
120 |
121 | private void setupRecyclerView(ActivityAboutBinding binding) {
122 | libraries.add(new GitRepository(null, getString(R.string.visit_wecan), null));
123 | libraries.add(new GitRepository(getString(R.string.xidian_university), getString(R.string.wecan_studio), getString(R.string.wecan_website)));
124 | libraries.add(new GitRepository(null, getString(R.string.visit_github), null));
125 | libraries.add(new GitRepository(getString(R.string.author), getString(R.string.app_name), getString(R.string.source_code)));
126 | libraries.add(new GitRepository(null, "Thanks to", null));
127 | libraries.add(new GitRepository("Square", "Okhttp", "https://square.github.io/okhttp"));
128 | libraries.add(new GitRepository("Square", "Retrofit", "https://square.github.io/retrofit"));
129 | libraries.add(new GitRepository("Google", "Gson", "https://github.com/google/gson"));
130 | libraries.add(new GitRepository("ReactiveX", "RxJava", "https://github.com/ReactiveX/RxJava"));
131 | libraries.add(new GitRepository("ReactiveX", "RxAndroid", "https://github.com/ReactiveX/RxAndroid"));
132 | libraries.add(new GitRepository("JakeWharton", "RxBinding", "https://github.com/JakeWharton/RxBinding"));
133 | libraries.add(new GitRepository("JakeWharton", "nineoldandroids", "https://github.com/JakeWharton/NineOldAndroids"));
134 | libraries.add(new GitRepository("Trello", "RxLifecycle", "https://github.com/trello/RxLifecycle"));
135 | libraries.add(new GitRepository("OXO", "mr-mantou-android", "https://github.com/oxoooo/mr-mantou-android"));
136 | libraries.add(new GitRepository("drakeet", "Meizhi", "https://github.com/drakeet/Meizhi"));
137 | libraries.add(new GitRepository("donglua", "PhotoPicker", "https://github.com/donglua/PhotoPicker"));
138 | libraries.add(new GitRepository("balysv", "material-ripple", "https://github.com/balysv/material-ripple"));
139 | binding.libraries.setAdapter(new LibrariesAdapter(libraries, getLayoutInflater(), this));
140 | }
141 |
142 |
143 | private void composeEmail(String address) {
144 | final Intent intent = new Intent(Intent.ACTION_SENDTO);
145 | intent.setData(Uri.parse("mailto:"));
146 | intent.putExtra(Intent.EXTRA_EMAIL, address);
147 | Observable.just(intent)
148 | .subscribeOn(Schedulers.io())
149 | .map(new Func1>() {
150 | @Override
151 | public List call(Intent intent) {
152 | return getPackageManager().queryIntentActivities(intent, MODE_PRIVATE);
153 | }
154 | })
155 | .observeOn(AndroidSchedulers.mainThread())
156 | .filter(new Func1, Boolean>() {
157 | @Override
158 | public Boolean call(List resolveInfo) {
159 | if (resolveInfo.size() == 0) {
160 | showSimpleDialog(R.string.no_email_app);
161 | return false;
162 | }
163 | return true;
164 | }
165 | })
166 | .compose(this.>bindToLifecycle())
167 | .subscribe(new Action1>() {
168 | @Override
169 | public void call(List resolveInfo) {
170 | startActivity(intent);
171 | }
172 | });
173 | }
174 |
175 | private void viewGitHub(String url) {
176 | Intent intent = new Intent(Intent.ACTION_VIEW);
177 | intent.setData(Uri.parse(url));
178 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
179 | startActivity(intent);
180 | }
181 |
182 | @Override
183 | public void onLibraryClick(LibrariesAdapter.ItemViewHolder holder) {
184 | int position = holder.getAdapterPosition();
185 | viewGitHub(libraries.get(position).url);
186 | }
187 |
188 |
189 | }
190 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wecan/xhin/studio/activity/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.wecan.xhin.studio.activity;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Intent;
5 | import android.databinding.DataBindingUtil;
6 | import android.os.Bundle;
7 |
8 | import com.jakewharton.rxbinding.view.RxView;
9 | import com.jakewharton.rxbinding.view.ViewClickEvent;
10 | import com.umeng.update.UmengUpdateAgent;
11 | import com.wecan.xhin.baselib.activity.BaseActivity;
12 | import com.wecan.xhin.baselib.rx.RxNetworking;
13 | import com.wecan.xhin.baselib.util.PreferenceHelper;
14 | import com.wecan.xhin.studio.App;
15 | import com.wecan.xhin.studio.R;
16 | import com.wecan.xhin.studio.api.Api;
17 | import com.wecan.xhin.studio.bean.common.User;
18 | import com.wecan.xhin.studio.databinding.ActivityLoginBinding;
19 |
20 | import java.io.IOException;
21 |
22 | import retrofit.HttpException;
23 | import rx.Observable;
24 | import rx.android.schedulers.AndroidSchedulers;
25 | import rx.functions.Action1;
26 | import rx.functions.Func0;
27 | import rx.schedulers.Schedulers;
28 |
29 | public class LoginActivity extends BaseActivity {
30 |
31 | private ActivityLoginBinding binding;
32 | private Observable observableConnect;
33 | private Api api;
34 |
35 |
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 |
40 |
41 | binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
42 | setSupportActionBar(binding.toolbar);
43 | api = App.from(this).createApi(Api.class);
44 | ProgressDialog pd = new ProgressDialog(this);
45 |
46 | Observable.Transformer networkingIndicator = RxNetworking.bindConnecting(pd);
47 |
48 | binding.setName(PreferenceHelper.getInstance(this).getString(App.KEY_PREFERENCE_USER, getString(R.string.nothing)));
49 | binding.setPhone(PreferenceHelper.getInstance(this).getString(App.KEY_PREFERENCE_PHONE, getString(R.string.nothing)));
50 |
51 | observableConnect = Observable
52 | //defer操作符是直到有订阅者订阅时,才通过Observable的工厂方法创建Observable并执行
53 | //defer操作符能够保证Observable的状态是最新的
54 | .defer(new Func0>() {
55 | @Override
56 | public Observable call() {
57 | return api.login(binding.etName.getText().toString(), binding.etPhone.getText().toString());
58 | }
59 | })
60 | .subscribeOn(Schedulers.io())
61 | .observeOn(AndroidSchedulers.mainThread())
62 | .compose(networkingIndicator);
63 |
64 | RxView.clickEvents(binding.btnLogin)
65 | .filter(new EditTextFilter(binding.etName, R.string.name_no_input))
66 | .filter(new EditTextFilter(binding.etPhone, R.string.phone_no_input))
67 | .compose(this.bindToLifecycle())
68 | .subscribe(new Action1() {
69 | @Override
70 | public void call(ViewClickEvent viewClickEvent) {
71 | login();
72 | }
73 | });
74 |
75 | setRxClick(binding.btnRegister)
76 | .compose(this.bindToLifecycle())
77 | .subscribe(new Action1() {
78 | @Override
79 | public void call(ViewClickEvent viewClickEvent) {
80 | startActivity(new Intent(LoginActivity.this, RegisterActivity.class));
81 | }
82 | });
83 |
84 | setupUmengUpdate();
85 | }
86 |
87 | private void login() {
88 | observableConnect
89 | .compose(this.bindToLifecycle())
90 | .subscribe(new Action1() {
91 | @Override
92 | public void call(User user) {
93 | PreferenceHelper.getInstance(LoginActivity.this).saveParam(App.KEY_PREFERENCE_USER, binding.etName.getText().toString());
94 | PreferenceHelper.getInstance(LoginActivity.this).saveParam(App.KEY_PREFERENCE_PHONE, binding.etPhone.getText().toString());
95 | startActivity(new Intent(LoginActivity.this, MainActivity.class).putExtra(MainActivity.KEY_USER, user));
96 | finish();
97 | }
98 | }, new Action1() {
99 | @Override
100 | public void call(Throwable throwable) {
101 | //事实上在code != 200 的时候 , 可以获取响应的body.
102 | if (throwable instanceof HttpException) {
103 | try {
104 | showSimpleDialog(R.string.login_fail, ((HttpException) throwable).response().errorBody().string());
105 | } catch (IOException e) {
106 | showSimpleDialog(R.string.login_fail, throwable.getMessage());
107 | }
108 | return;
109 | }
110 | showSimpleDialog(R.string.login_fail, throwable.getMessage());
111 | }
112 | });
113 | }
114 |
115 |
116 | private void setupUmengUpdate() {
117 | UmengUpdateAgent.update(this);
118 | UmengUpdateAgent.setDeltaUpdate(false);
119 | UmengUpdateAgent.setUpdateOnlyWifi(false);
120 | }
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wecan/xhin/studio/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wecan.xhin.studio.activity;
2 |
3 | import android.content.Intent;
4 | import android.databinding.DataBindingUtil;
5 | import android.os.Bundle;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v4.app.FragmentTransaction;
8 | import android.support.v4.view.GravityCompat;
9 | import android.support.v4.widget.DrawerLayout;
10 | import android.support.v7.app.ActionBarDrawerToggle;
11 | import android.view.MenuItem;
12 |
13 | import com.jakewharton.rxbinding.support.design.widget.RxNavigationView;
14 | import com.jakewharton.rxbinding.support.v4.widget.RxDrawerLayout;
15 | import com.wecan.xhin.baselib.activity.BaseActivity;
16 | import com.wecan.xhin.studio.R;
17 | import com.wecan.xhin.studio.bean.common.User;
18 | import com.wecan.xhin.studio.databinding.ActivityMainBinding;
19 | import com.wecan.xhin.studio.databinding.IncludeNavHeaderMainBinding;
20 | import com.wecan.xhin.studio.fragment.AllUserFragment;
21 | import com.wecan.xhin.studio.fragment.SignedUserFragment;
22 | import com.wecan.xhin.studio.fragment.BooksFragment;
23 |
24 | import rx.functions.Action1;
25 | import rx.functions.Func1;
26 |
27 | public class MainActivity extends BaseActivity {
28 |
29 | public static final String KEY_USER = "user";
30 | public static final int REQUEST_MY_DETAIL = 0;
31 |
32 | private ActivityMainBinding binding;
33 | private IncludeNavHeaderMainBinding headerBinding;
34 | private User user;
35 | private Fragment signedUserFragment, allFellowFragment, booksFragment;
36 |
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
42 | setSupportActionBar(binding.toolbar);
43 |
44 | user = getIntent().getParcelableExtra(KEY_USER);
45 | binding.setUser(user);
46 |
47 | ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, binding.drawerLayout,
48 | binding.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
49 | binding.drawerLayout.setDrawerListener(toggle);
50 | toggle.syncState();
51 |
52 |
53 | headerBinding = DataBindingUtil
54 | .inflate(getLayoutInflater(), R.layout.include_nav_header_main, null, false);
55 | headerBinding.setUser(user);
56 | binding.navView.addHeaderView(headerBinding.getRoot());
57 |
58 |
59 | RxNavigationView.itemSelections(binding.navView)
60 | .map(new Func1