├── .gitignore
├── .idea
├── .name
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
├── runConfigurations.xml
└── vcs.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── libs
│ ├── BaiduLBS_Android.jar
│ ├── arm64-v8a
│ │ ├── libBaiduMapSDK_base_v4_0_0.so
│ │ ├── libBaiduMapSDK_cloud_v4_0_0.so
│ │ ├── libBaiduMapSDK_map_v4_0_0.so
│ │ ├── libBaiduMapSDK_radar_v4_0_0.so
│ │ ├── libBaiduMapSDK_search_v4_0_0.so
│ │ ├── libBaiduMapSDK_util_v4_0_0.so
│ │ └── liblocSDK6a.so
│ ├── armeabi-v7a
│ │ ├── libBaiduMapSDK_base_v4_0_0.so
│ │ ├── libBaiduMapSDK_cloud_v4_0_0.so
│ │ ├── libBaiduMapSDK_map_v4_0_0.so
│ │ ├── libBaiduMapSDK_radar_v4_0_0.so
│ │ ├── libBaiduMapSDK_search_v4_0_0.so
│ │ ├── libBaiduMapSDK_util_v4_0_0.so
│ │ └── liblocSDK6a.so
│ ├── armeabi
│ │ ├── libBaiduMapSDK_base_v4_0_0.so
│ │ ├── libBaiduMapSDK_cloud_v4_0_0.so
│ │ ├── libBaiduMapSDK_map_v4_0_0.so
│ │ ├── libBaiduMapSDK_radar_v4_0_0.so
│ │ ├── libBaiduMapSDK_search_v4_0_0.so
│ │ ├── libBaiduMapSDK_util_v4_0_0.so
│ │ └── liblocSDK6a.so
│ ├── x86
│ │ ├── libBaiduMapSDK_base_v4_0_0.so
│ │ ├── libBaiduMapSDK_cloud_v4_0_0.so
│ │ ├── libBaiduMapSDK_map_v4_0_0.so
│ │ ├── libBaiduMapSDK_radar_v4_0_0.so
│ │ ├── libBaiduMapSDK_search_v4_0_0.so
│ │ ├── libBaiduMapSDK_util_v4_0_0.so
│ │ └── liblocSDK6a.so
│ └── x86_64
│ │ ├── libBaiduMapSDK_base_v4_0_0.so
│ │ ├── libBaiduMapSDK_cloud_v4_0_0.so
│ │ ├── libBaiduMapSDK_map_v4_0_0.so
│ │ ├── libBaiduMapSDK_radar_v4_0_0.so
│ │ ├── libBaiduMapSDK_search_v4_0_0.so
│ │ ├── libBaiduMapSDK_util_v4_0_0.so
│ │ └── liblocSDK6a.so
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── happyheng
│ │ └── sport_android
│ │ └── ApplicationTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── happyheng
│ │ │ └── sport_android
│ │ │ ├── App.java
│ │ │ ├── activity
│ │ │ ├── ActivityMain.java
│ │ │ ├── ActivitySportList.java
│ │ │ ├── ActivitySportMessage.java
│ │ │ ├── ArticleActivity.java
│ │ │ ├── BaseActivity.java
│ │ │ ├── LoginActivity.java
│ │ │ ├── MapActivity.java
│ │ │ └── RegisterActivity.java
│ │ │ ├── fragment
│ │ │ ├── FragmentMine.java
│ │ │ ├── FragmentNews.java
│ │ │ ├── FragmentSport.java
│ │ │ └── recycler
│ │ │ │ ├── FragmentBaseRecycler.java
│ │ │ │ └── FragmentLoadRecycler.java
│ │ │ ├── model
│ │ │ ├── IdEntity.java
│ │ │ ├── News.java
│ │ │ ├── User.java
│ │ │ ├── entity
│ │ │ │ ├── BaseResult.java
│ │ │ │ ├── Location.java
│ │ │ │ ├── NewsResult.java
│ │ │ │ ├── PostRequestBody.java
│ │ │ │ ├── SportListResult.java
│ │ │ │ └── SportMessageResult.java
│ │ │ ├── event
│ │ │ │ └── LocationEvent.java
│ │ │ ├── network
│ │ │ │ ├── HttpClient.java
│ │ │ │ ├── HttpClientRequestHelper.java
│ │ │ │ └── listener
│ │ │ │ │ └── OnRequestListener.java
│ │ │ └── request
│ │ │ │ ├── BaseRequest.java
│ │ │ │ ├── LoginRequest.java
│ │ │ │ ├── NewsRequest.java
│ │ │ │ ├── RecordSportMessageRequest.java
│ │ │ │ ├── RegisterRequest.java
│ │ │ │ ├── SportIdRequest.java
│ │ │ │ ├── SportListRequest.java
│ │ │ │ └── SportMessageRequest.java
│ │ │ ├── service
│ │ │ └── LocationService.java
│ │ │ ├── servicecode
│ │ │ ├── RecordService.java
│ │ │ └── impl
│ │ │ │ └── RecordServiceImpl.java
│ │ │ ├── utils
│ │ │ ├── AESUtils.java
│ │ │ ├── DensityUtils.java
│ │ │ ├── HexUtils.java
│ │ │ ├── NetUtils.java
│ │ │ ├── SPUtils.java
│ │ │ ├── ScreenUtils.java
│ │ │ ├── SimpleStartActivityUtils.java
│ │ │ ├── ThreadUtils.java
│ │ │ └── ToastUtils.java
│ │ │ └── view
│ │ │ ├── MainBottomView.java
│ │ │ ├── NewsItemView.java
│ │ │ └── TabSportBackView.java
│ └── res
│ │ ├── drawable
│ │ ├── bg_oval.xml
│ │ ├── bg_tab_information.xml
│ │ ├── bg_tab_mine.xml
│ │ ├── bg_tab_sport.xml
│ │ ├── bg_tab_sport_button.xml
│ │ ├── bg_tab_sport_button_press.xml
│ │ └── bg_tab_sport_normal.xml
│ │ ├── layout
│ │ ├── activity_article.xml
│ │ ├── activity_login.xml
│ │ ├── activity_main.xml
│ │ ├── activity_map.xml
│ │ ├── activity_register.xml
│ │ ├── activity_sport_list.xml
│ │ ├── activity_sport_message.xml
│ │ ├── fragment_base_recycler.xml
│ │ ├── fragment_information.xml
│ │ ├── fragment_mine.xml
│ │ ├── fragment_sport.xml
│ │ ├── item_load_more.xml
│ │ ├── item_news.xml
│ │ ├── item_sport_list.xml
│ │ └── view_main_bottom.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── tab_information_selected.png
│ │ ├── tab_information_unselected.png
│ │ ├── tab_me_selected.png
│ │ ├── tab_me_unselected.png
│ │ ├── tab_sport_selected.png
│ │ └── tab_sport_unselected.png
│ │ ├── mipmap-xxhdpi
│ │ ├── tab_me_selected.png
│ │ ├── tab_me_unselected.png
│ │ ├── tab_sport_selected.png
│ │ ├── tab_sport_unselected.png
│ │ └── user_icon.jpg
│ │ ├── mipmap-xxxhdpi
│ │ └── icon.jpg
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── happyheng
│ └── sport_android
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshot
├── 1.png
├── 2.png
├── 3.png
├── 4.png
└── 5.png
└── 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 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Sport_Android
--------------------------------------------------------------------------------
/.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/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
22 |
23 |
--------------------------------------------------------------------------------
/.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 | Android
39 |
40 |
41 | Android > Lint > Correctness
42 |
43 |
44 | Java
45 |
46 |
47 | Java language level migration aidsJava
48 |
49 |
50 |
51 |
52 | Android
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | 1.8
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 描述
2 | 一个Android版的运动APP。其实现了登陆、注册、资讯详情、运动记录等功能。
3 |
4 | #技术栈
5 | [okhttp](https://github.com/square/okhttp) 为项目的网络请求库
6 |
7 | [fastjson](https://github.com/alibaba/fastjson) 为项目中的json解析库
8 |
9 | [eventbus](https://github.com/greenrobot/EventBus) 为项目中的发布/订阅事件总线
10 |
11 | [glide](https://github.com/bumptech/glide) 为项目中的图片加载框架
12 | # 如何使用
13 | 此APP需与相应的服务端源码配合使用,当然,服务端源码也是开源的,链接为: [服务器端源码](https://github.com/happyheng/Sport_Service)
14 |
15 | 需要注意的是,在clone了服务器端代码进行使用时,需要找到自己电脑的ip地址,然后把Android中BaseRequest的IP变量换成自己电脑的ip地址,否则访问会失败。
16 |
17 | #程序截图
18 |
19 |
20 |
21 |
22 |
23 |
24 | # 更多
25 | 关于此APP的设计我会在博客中做出更多的介绍,欢迎大家参观我的博客: [博客](http://blog.csdn.net/happyheng)
26 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.happyheng.sport_android"
9 | minSdkVersion 14
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | sourceSets {
22 | main() {
23 | jniLibs.srcDirs = ['libs']
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | compile fileTree(dir: 'libs', include: ['*.jar'])
30 | testCompile 'junit:junit:4.12'
31 | compile 'com.android.support:appcompat-v7:23.1.1'
32 | compile 'com.android.support:recyclerview-v7:+'
33 |
34 | compile 'com.squareup.okhttp3:okhttp:3.3.1'
35 | compile 'com.github.orhanobut:logger:1.12'
36 | compile 'com.alibaba:fastjson:1.1.46.android'
37 | compile 'org.greenrobot:eventbus:3.0.0'
38 | compile files('libs/BaiduLBS_Android.jar')
39 | compile 'com.github.bumptech.glide:glide:3.7.0'
40 | }
41 |
--------------------------------------------------------------------------------
/app/libs/BaiduLBS_Android.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/BaiduLBS_Android.jar
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_base_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_base_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_cloud_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_cloud_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_map_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_map_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_radar_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_radar_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_search_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_search_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/libBaiduMapSDK_util_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/libBaiduMapSDK_util_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/arm64-v8a/liblocSDK6a.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/arm64-v8a/liblocSDK6a.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_base_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_base_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_cloud_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_cloud_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_map_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_map_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_radar_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_radar_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_search_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_search_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/libBaiduMapSDK_util_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/libBaiduMapSDK_util_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi-v7a/liblocSDK6a.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi-v7a/liblocSDK6a.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_base_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_base_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_cloud_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_cloud_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_map_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_map_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_radar_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_radar_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_search_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_search_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/libBaiduMapSDK_util_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/libBaiduMapSDK_util_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/armeabi/liblocSDK6a.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/armeabi/liblocSDK6a.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_base_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_base_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_cloud_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_cloud_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_map_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_map_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_radar_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_radar_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_search_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_search_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/libBaiduMapSDK_util_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/libBaiduMapSDK_util_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86/liblocSDK6a.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86/liblocSDK6a.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_base_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_base_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_cloud_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_cloud_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_map_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_map_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_radar_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_radar_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_search_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_search_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/libBaiduMapSDK_util_v4_0_0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/libBaiduMapSDK_util_v4_0_0.so
--------------------------------------------------------------------------------
/app/libs/x86_64/liblocSDK6a.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/libs/x86_64/liblocSDK6a.so
--------------------------------------------------------------------------------
/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 /Users/liuheng/Desktop/Android/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/androidTest/java/com/happyheng/sport_android/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android;
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 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
42 |
43 |
44 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
66 |
67 |
68 |
71 |
72 |
73 |
74 |
77 |
78 |
79 |
80 |
82 |
83 |
84 |
85 |
87 |
88 |
89 |
90 |
92 |
93 |
94 |
95 |
96 |
100 |
101 |
102 |
103 |
104 |
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/App.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android;
2 |
3 | import android.app.Application;
4 |
5 | import com.baidu.mapapi.SDKInitializer;
6 | import com.happyheng.sport_android.model.User;
7 | import com.happyheng.sport_android.model.network.HttpClient;
8 | import com.orhanobut.logger.Logger;
9 |
10 | /**
11 | * 程序的Application对象
12 | * Created by liuheng on 16/6/7.
13 | */
14 | public class App extends Application{
15 |
16 | private static final String TAG_NAME = "MY_TAG";
17 |
18 | @Override
19 | public void onCreate() {
20 | super.onCreate();
21 |
22 | //可以在Application对象中初始化一些类库
23 |
24 | Logger.init(TAG_NAME);
25 | HttpClient.init(this);
26 |
27 | User.init(getApplicationContext());
28 |
29 | SDKInitializer.initialize(getApplicationContext());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/ActivityMain.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 |
6 | import com.happyheng.sport_android.R;
7 | import com.happyheng.sport_android.fragment.FragmentNews;
8 | import com.happyheng.sport_android.fragment.FragmentMine;
9 | import com.happyheng.sport_android.fragment.FragmentSport;
10 | import com.happyheng.sport_android.view.MainBottomView;
11 | import com.orhanobut.logger.Logger;
12 |
13 | /**
14 | * 主页面
15 | * Created by liuheng on 16/7/12.
16 | */
17 | public class ActivityMain extends BaseActivity {
18 |
19 | private static final String FRAGMENT_BASE_TAG = "base_fragment";
20 |
21 | private MainBottomView mBottomView;
22 |
23 | private int mSelectPosition = 0;
24 |
25 | private MainBottomView.OnBottomChooseListener mBottomChooseListener = new BottomChooseListener();
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_main);
31 |
32 | initView();
33 |
34 | selectPositionFragment(mSelectPosition);
35 | }
36 |
37 | private void initView() {
38 | mBottomView = (MainBottomView) findViewById(R.id.main_bottom_tab);
39 | mBottomView.setBottomCLickListener(mBottomChooseListener);
40 | }
41 |
42 | //初始化一个Fragment,并将其添加到指定位置
43 | private void initFragment(int position){
44 |
45 | Fragment fragment;
46 | switch (position){
47 |
48 | case 0:
49 | fragment = new FragmentNews();
50 | break;
51 |
52 | case 1:
53 | fragment = new FragmentSport();
54 | break;
55 |
56 | default:
57 | fragment = new FragmentMine();
58 | break;
59 | }
60 | getSupportFragmentManager().beginTransaction().add(R.id.main_content_ll,fragment,getFragmentTagByPosition(position)).commit();
61 | }
62 |
63 | //得到指定Tag的Fragment
64 | private Fragment getFragmentByTag(int position){
65 | return getSupportFragmentManager().findFragmentByTag(getFragmentTagByPosition(position));
66 | }
67 |
68 | //得到每个Fragment对应的tag
69 | private String getFragmentTagByPosition(int position){
70 | return FRAGMENT_BASE_TAG + position;
71 | }
72 |
73 | private void selectPositionFragment(int position){
74 | Fragment selectFragment = getFragmentByTag(position);
75 |
76 | if (selectFragment == null){
77 | initFragment(position);
78 | } else {
79 | getSupportFragmentManager().beginTransaction().show(selectFragment).commit();
80 | }
81 | }
82 |
83 |
84 | private class BottomChooseListener implements MainBottomView.OnBottomChooseListener {
85 |
86 | @Override
87 | public void onClick(int oldPosition, int selectPosition) {
88 |
89 | Fragment nowFragment = getFragmentByTag(oldPosition);
90 | getSupportFragmentManager().beginTransaction().hide(nowFragment).commit();
91 | selectPositionFragment(selectPosition);
92 |
93 | mSelectPosition = selectPosition;
94 | }
95 | }
96 |
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/ActivitySportList.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.AdapterView;
10 | import android.widget.BaseAdapter;
11 | import android.widget.ListView;
12 | import android.widget.TextView;
13 |
14 | import com.happyheng.sport_android.R;
15 | import com.happyheng.sport_android.model.User;
16 | import com.happyheng.sport_android.model.request.SportListRequest;
17 | import com.orhanobut.logger.Logger;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | /**
23 | * 显示所有运动记录的Activity
24 | * Created by liuheng on 16/8/15.
25 | */
26 | public class ActivitySportList extends BaseActivity implements SportListRequest.ListListener,ListView.OnItemClickListener{
27 |
28 | private ListView mSportList;
29 | private SportListAdapter mAdapter;
30 | private List mListData = new ArrayList<>();
31 |
32 | @Override
33 | protected void onCreate(@Nullable Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.activity_sport_list);
36 |
37 | initView();
38 | initData();
39 | }
40 |
41 | private void initView() {
42 | mSportList = (ListView) findViewById(R.id.sport_list_lv);
43 | mAdapter = new SportListAdapter();
44 | mSportList.setAdapter(mAdapter);
45 | mSportList.setOnItemClickListener(this);
46 | }
47 |
48 | private void initData() {
49 | SportListRequest request = new SportListRequest(User.getUser().getUserToken());
50 | request.setListListener(this);
51 | request.doRequest();
52 | }
53 |
54 | @Override
55 | public void onSuccess(List list) {
56 | mListData.addAll(list);
57 | mAdapter.notifyDataSetChanged();
58 | }
59 |
60 | @Override
61 | public void onFail() {
62 | Logger.d("获取失败");
63 | }
64 |
65 | @Override
66 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
67 | int sportId = mListData.get(position);
68 | Logger.d("得到的sportId为"+sportId);
69 |
70 | Intent intent = new Intent(this,ActivitySportMessage.class);
71 | intent.putExtra(ActivitySportMessage.TAG_SPORT_ID,sportId);
72 | startActivity(intent);
73 | }
74 |
75 | private class SportListAdapter extends BaseAdapter{
76 |
77 | @Override
78 | public int getCount() {
79 | return mListData.size();
80 | }
81 |
82 | @Override
83 | public Object getItem(int position) {
84 | return null;
85 | }
86 |
87 | @Override
88 | public long getItemId(int position) {
89 | return 0;
90 | }
91 |
92 | @Override
93 | public View getView(int position, View convertView, ViewGroup parent) {
94 |
95 | if (convertView == null){
96 | convertView = LayoutInflater.from(ActivitySportList.this).inflate(R.layout.item_sport_list,null);
97 | }
98 | TextView textView = (TextView) convertView.findViewById(R.id.item_sport_list_tv);
99 | textView.setText("运动轨迹"+(position+1));
100 |
101 | return convertView;
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/ActivitySportMessage.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 |
6 | import com.baidu.mapapi.map.BaiduMap;
7 | import com.baidu.mapapi.map.DotOptions;
8 | import com.baidu.mapapi.map.MapStatus;
9 | import com.baidu.mapapi.map.MapStatusUpdateFactory;
10 | import com.baidu.mapapi.map.MapView;
11 | import com.baidu.mapapi.map.MyLocationConfiguration;
12 | import com.baidu.mapapi.map.MyLocationData;
13 | import com.baidu.mapapi.map.OverlayOptions;
14 | import com.baidu.mapapi.map.PolygonOptions;
15 | import com.baidu.mapapi.map.PolylineOptions;
16 | import com.baidu.mapapi.model.LatLng;
17 | import com.happyheng.sport_android.R;
18 | import com.happyheng.sport_android.model.User;
19 | import com.happyheng.sport_android.model.entity.Location;
20 | import com.happyheng.sport_android.model.request.BaseRequest;
21 | import com.happyheng.sport_android.model.request.SportMessageRequest;
22 | import com.orhanobut.logger.Logger;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | /**
28 | * 显示运动轨迹的Activity
29 | * Created by liuheng on 16/8/16.
30 | */
31 | public class ActivitySportMessage extends BaseActivity implements SportMessageRequest.OnSportMessageListener{
32 |
33 | public static final String TAG_SPORT_ID = "sport_id";
34 |
35 | //显示的百度MapView
36 | private MapView mMapView = null;
37 | private BaiduMap mMap = null;
38 |
39 | private int mSportId;
40 | private SportMessageRequest request;
41 |
42 | @Override
43 | protected void onCreate(@Nullable Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | setContentView(R.layout.activity_sport_message);
46 |
47 | initView();
48 | getData();
49 | }
50 |
51 | private void initView() {
52 | //获取地图控件引用
53 | mMapView = (MapView) findViewById(R.id.bmapView);
54 | mMap = mMapView.getMap();
55 | }
56 |
57 | private void getData(){
58 | mSportId = getIntent().getIntExtra(TAG_SPORT_ID,0);
59 | request = new SportMessageRequest(User.getUser().getUserToken(),String.valueOf(mSportId));
60 | request.setMessageListener(this);
61 | request.doRequest();
62 | }
63 |
64 | @Override
65 | public void onSuccess(List data) {
66 |
67 | if (!data.isEmpty()){
68 | Location firstLocation = data.get(0);
69 |
70 | //1、定位至第一个点,然后缩小地图范围
71 | //此为设置缩放比例为15级
72 | mMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(new MapStatus.Builder().zoom(18).build()));
73 | LatLng firstLatLng = new LatLng(firstLocation.getPosy(),firstLocation.getPosx());
74 | location(firstLatLng);
75 |
76 | //2、绘制运动信息
77 | List latLngList = new ArrayList<>();
78 | List optionsList = new ArrayList<>();
79 | for (Location location : data){
80 | LatLng latLng = new LatLng(location.getPosy(),location.getPosx());
81 | latLngList.add(latLng);
82 |
83 | OverlayOptions options = new DotOptions().center(latLng);
84 | optionsList.add(options);
85 | }
86 |
87 | //画点
88 | mMap.addOverlays(optionsList);
89 |
90 | //画折线
91 | if(latLngList.size() != 1){
92 | OverlayOptions lineOptions = new PolylineOptions().points(latLngList);
93 | mMap.addOverlay(lineOptions);
94 | }
95 | }
96 | }
97 |
98 |
99 | //根据定位信息进行定位,即移动地图至当前点
100 | private void location(LatLng bdLocation) {
101 |
102 | //可以用下面的方法对在得到经纬度信息后在百度地图中进行显示
103 | BaiduMap mMap = mMapView.getMap();
104 |
105 | // 开启定位图层
106 | mMap.setMyLocationEnabled(true);
107 | // 构造定位数据
108 | MyLocationData locData = new MyLocationData.Builder()
109 | // 此处设置开发者获取到的方向信息,顺时针0-360
110 | .direction(100)
111 | .latitude(bdLocation.latitude)
112 | .longitude(bdLocation.longitude)
113 | .build();
114 |
115 | //设置定位的配置信息
116 | MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.FOLLOWING, true, null);
117 | mMap.setMyLocationConfigeration(configuration);
118 | // 设置定位数据
119 | mMap.setMyLocationData(locData);
120 | }
121 |
122 | @Override
123 | public void onFail() {
124 | Logger.d("请求失败");
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/ArticleActivity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.view.View;
6 | import android.webkit.WebSettings;
7 | import android.webkit.WebView;
8 |
9 | import com.happyheng.sport_android.R;
10 | import com.orhanobut.logger.Logger;
11 |
12 | /**
13 | * 文章详情界面
14 | * Created by liuheng on 16/7/27.
15 | */
16 | public class ArticleActivity extends BaseActivity {
17 |
18 | public static final String BUNDLE_URL = "url";
19 | //private static final String TEST_URL = "http://192.168.0.104:8080/Sport/NewsDetail?id=3";
20 |
21 | private WebView mWebView;
22 |
23 | //文章的url
24 | private String mArticleUrl;
25 |
26 |
27 | @Override
28 | protected void onCreate(@Nullable Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_article);
31 | mWebView = (WebView) findViewById(R.id.article_wv);
32 |
33 | initWebView();
34 |
35 | mArticleUrl = getIntent().getStringExtra(BUNDLE_URL);
36 |
37 | mWebView.loadUrl(mArticleUrl);
38 | }
39 |
40 | private void initWebView() {
41 | WebSettings settings = mWebView.getSettings();
42 |
43 | settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
44 | settings.setUseWideViewPort(true);
45 | settings.setLoadWithOverviewMode(true);
46 | mWebView.setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.app.Activity;
4 | import android.support.v4.app.FragmentActivity;
5 | import android.widget.Toast;
6 |
7 | /**
8 | * 项目中所有Activity的基类
9 | * Created by liuheng on 16/6/26.
10 | */
11 | public class BaseActivity extends FragmentActivity{
12 |
13 | protected void showToast(String toast){
14 | Toast.makeText(this,toast,Toast.LENGTH_LONG).show();
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.animation.ObjectAnimator;
4 | import android.animation.PropertyValuesHolder;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.text.TextUtils;
8 | import android.view.View;
9 | import android.widget.Button;
10 | import android.widget.EditText;
11 | import android.widget.ImageView;
12 |
13 | import com.happyheng.sport_android.R;
14 | import com.happyheng.sport_android.model.request.BaseRequest;
15 | import com.happyheng.sport_android.model.request.LoginRequest;
16 | import com.happyheng.sport_android.model.User;
17 | import com.happyheng.sport_android.utils.DensityUtils;
18 | import com.happyheng.sport_android.utils.ScreenUtils;
19 | import com.happyheng.sport_android.utils.SimpleStartActivityUtils;
20 | import com.happyheng.sport_android.utils.ToastUtils;
21 | import com.orhanobut.logger.Logger;
22 |
23 | /**
24 | * "登陆"的Activity
25 | * Created by liuheng on 16/6/6.
26 | */
27 | public class LoginActivity extends BaseActivity {
28 |
29 | //动画的时长
30 | private static final int ANIMATION_TIME = 1000;
31 | //底部Button距中间线的高度
32 | private static final int BOTTOM_MARGIN = 50;
33 |
34 | private View.OnClickListener mLoginBtClickListener = new OnLoginBtClickListener();
35 | private LoginRequest.OnLoginListener mLoginListener = new OnLoginListener();
36 |
37 | private ImageView mIconIv;
38 | private EditText mUserNameEt, mPassWordEt;
39 | private Button mLoginBt, mRegisterBt;
40 |
41 | private View mTopLl, mBottomLl;
42 |
43 |
44 | @Override
45 | protected void onCreate(Bundle savedInstanceState) {
46 | super.onCreate(savedInstanceState);
47 | setContentView(R.layout.activity_login);
48 |
49 | initView();
50 |
51 | beginAnimation();
52 | }
53 |
54 |
55 | /**
56 | * 初始化所有的View
57 | */
58 | private void initView() {
59 | mIconIv = (ImageView) findViewById(R.id.icon_iv);
60 | mUserNameEt = (EditText) findViewById(R.id.username_et);
61 | mPassWordEt = (EditText) findViewById(R.id.password_et);
62 | mLoginBt = (Button) findViewById(R.id.login_bt);
63 | mRegisterBt = (Button) findViewById(R.id.register_bt);
64 |
65 | mTopLl = findViewById(R.id.top_ll);
66 | mBottomLl = findViewById(R.id.bottom_ll);
67 |
68 | mLoginBt.setOnClickListener(mLoginBtClickListener);
69 |
70 | mRegisterBt.setOnClickListener(new View.OnClickListener() {
71 | @Override
72 | public void onClick(View v) {
73 | //点击注册,跳转到注册的界面
74 | SimpleStartActivityUtils.startActivity(LoginActivity.this, RegisterActivity.class);
75 | }
76 | });
77 | }
78 |
79 | private class OnLoginBtClickListener implements View.OnClickListener {
80 |
81 | @Override
82 | public void onClick(View v) {
83 | String userNameString = mUserNameEt.getText().toString();
84 | String passWordString = mPassWordEt.getText().toString();
85 | //1、先判断是否为空
86 | if (TextUtils.isEmpty(userNameString) || TextUtils.isEmpty(passWordString)) {
87 | ToastUtils.showToast(LoginActivity.this, getResources().getString(R.string.user_pass_empty));
88 | }
89 | //2、判断是否为用户名为字母+数字
90 |
91 |
92 | //3、调用相关接口
93 | BaseRequest request = new LoginRequest(userNameString, passWordString, mLoginListener);
94 | request.doRequest();
95 | }
96 | }
97 |
98 | private class OnLoginListener implements LoginRequest.OnLoginListener{
99 |
100 | @Override
101 | public void onSuccess(String token) {
102 |
103 | User.getUser().setUserToken(token);
104 |
105 | Intent intent = new Intent(LoginActivity.this, ActivityMain.class);
106 | startActivity(intent);
107 | }
108 |
109 |
110 | @Override
111 | public void onFail(int code) {
112 | Logger.d("失败的code为" + code);
113 |
114 | switch (code) {
115 |
116 | case LoginRequest.REQUEST_WRONG_USERNAME:
117 | ToastUtils.showToast(LoginActivity.this, getResources().getString(R.string.wrong_username));
118 |
119 | break;
120 |
121 | case LoginRequest.REQUEST_WRONG_PASSWORD:
122 | ToastUtils.showToast(LoginActivity.this, getResources().getString(R.string.wrong_password));
123 |
124 | break;
125 |
126 | default:
127 | ToastUtils.showToast(LoginActivity.this, getResources().getString(R.string.wrong_request));
128 |
129 | break;
130 | }
131 | }
132 | }
133 |
134 | /**
135 | * 开始动画
136 | */
137 | private void beginAnimation() {
138 |
139 | final int screenHeight = ScreenUtils.getScreenHeight(this);
140 |
141 | mTopLl.post(new Runnable() {
142 | @Override
143 | public void run() {
144 | int topLlHeight = mTopLl.getMeasuredHeight();
145 | int animationHeight = screenHeight / 2 - topLlHeight;
146 |
147 | PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationY", animationHeight);
148 | PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("alpha", 0.3f, 1.0f);
149 |
150 | ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTopLl, holder1, holder2);
151 | animator.setDuration(ANIMATION_TIME);
152 | animator.start();
153 | }
154 | });
155 |
156 | mBottomLl.post(new Runnable() {
157 | @Override
158 | public void run() {
159 | int animationHeight = screenHeight / 2 + DensityUtils.dp2px(LoginActivity.this, BOTTOM_MARGIN) - mBottomLl.getTop();
160 |
161 | PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationY", animationHeight);
162 | PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("alpha", 0.3f, 1.0f);
163 |
164 | ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mBottomLl, holder1, holder2);
165 | animator.setDuration(ANIMATION_TIME);
166 | animator.start();
167 | }
168 | });
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/MapActivity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 |
6 | import com.baidu.location.BDLocation;
7 | import com.baidu.location.BDLocationListener;
8 | import com.baidu.location.LocationClient;
9 | import com.baidu.location.LocationClientOption;
10 | import com.baidu.mapapi.map.BaiduMap;
11 | import com.baidu.mapapi.map.DotOptions;
12 | import com.baidu.mapapi.map.MapStatus;
13 | import com.baidu.mapapi.map.MapStatusUpdateFactory;
14 | import com.baidu.mapapi.map.MapView;
15 | import com.baidu.mapapi.map.MyLocationConfiguration;
16 | import com.baidu.mapapi.map.MyLocationData;
17 | import com.baidu.mapapi.map.OverlayOptions;
18 | import com.baidu.mapapi.map.PolylineOptions;
19 | import com.baidu.mapapi.model.LatLng;
20 | import com.happyheng.sport_android.R;
21 | import com.happyheng.sport_android.model.event.LocationEvent;
22 | import com.happyheng.sport_android.service.LocationService;
23 | import com.happyheng.sport_android.servicecode.RecordService;
24 | import com.happyheng.sport_android.servicecode.impl.RecordServiceImpl;
25 | import com.orhanobut.logger.Logger;
26 |
27 | import org.greenrobot.eventbus.EventBus;
28 | import org.greenrobot.eventbus.Subscribe;
29 |
30 | import java.util.ArrayList;
31 | import java.util.LinkedList;
32 | import java.util.List;
33 |
34 | /**
35 | * 地图的Activity
36 | * Created by liuheng on 16/6/26.
37 | */
38 | public class MapActivity extends BaseActivity {
39 |
40 | //显示的百度MapView
41 | private MapView mMapView = null;
42 | private BaiduMap mMap = null;
43 |
44 | private LatLng mBeforeLocation = null;
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | setContentView(R.layout.activity_map);
50 |
51 | //获取地图控件引用
52 | mMapView = (MapView) findViewById(R.id.bmapView);
53 | mMap = mMapView.getMap();
54 |
55 | startLocationService();
56 |
57 | EventBus.getDefault().register(this);
58 | }
59 |
60 | //启动定位的Service
61 | private void startLocationService(){
62 | Intent intent = new Intent(this, LocationService.class);
63 | startService(intent);
64 | }
65 |
66 | //获取经纬度后回调的方法
67 | @Subscribe
68 | public void onEvent(LocationEvent bdLocation) {
69 | //先暂时获得经纬度信息,并将其记录在List中
70 | //进行定位
71 | location(bdLocation.getLocation());
72 |
73 | //绘制位置
74 | drawLocation(bdLocation.getLocation());
75 | }
76 |
77 | //根据定位信息进行定位,即移动地图至当前点
78 | private void location(LatLng bdLocation) {
79 |
80 | //将map缩放至18级
81 | mMap.setMapStatus(MapStatusUpdateFactory.newMapStatus(new MapStatus.Builder().zoom(18).build()));
82 |
83 | //可以用下面的方法对在得到经纬度信息后在百度地图中进行显示
84 | BaiduMap mMap = mMapView.getMap();
85 |
86 | // 开启定位图层
87 | mMap.setMyLocationEnabled(true);
88 | // 构造定位数据
89 | MyLocationData locData = new MyLocationData.Builder()
90 | // 此处设置开发者获取到的方向信息,顺时针0-360
91 | .direction(100)
92 | .latitude(bdLocation.latitude)
93 | .longitude(bdLocation.longitude)
94 | .build();
95 |
96 | //设置定位的配置信息
97 | MyLocationConfiguration configuration = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.FOLLOWING, true, null);
98 | mMap.setMyLocationConfigeration(configuration);
99 | // 设置定位数据
100 | mMap.setMyLocationData(locData);
101 | }
102 |
103 | //根据当前的坐标画出点数和直线
104 | private void drawLocation(LatLng nowLatLng) {
105 |
106 | //1、画出当前的点数
107 | OverlayOptions dotOptions = new DotOptions().center(nowLatLng);
108 | mMap.addOverlay(dotOptions);
109 |
110 | //2、如果不为1,那么还要画一个指向之前的横线
111 | if (mBeforeLocation != null){
112 | List linePoints = new ArrayList<>();
113 | linePoints.add(mBeforeLocation);
114 | linePoints.add(nowLatLng);
115 | OverlayOptions lineOptions = new PolylineOptions().points(linePoints);
116 | mMap.addOverlay(lineOptions);
117 | }
118 | mBeforeLocation = nowLatLng;
119 | }
120 |
121 | @Override
122 | protected void onResume() {
123 | super.onResume();
124 | //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
125 | mMapView.onResume();
126 | }
127 |
128 | @Override
129 | protected void onPause() {
130 | super.onPause();
131 | //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
132 | mMapView.onPause();
133 | }
134 |
135 |
136 | @Override
137 | protected void onDestroy() {
138 | super.onDestroy();
139 | //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
140 | mMapView.onDestroy();
141 |
142 | //将定位Service关闭掉
143 | Intent intent = new Intent(this, LocationService.class);
144 | stopService(intent);
145 | }
146 |
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/activity/RegisterActivity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.activity;
2 |
3 | import android.os.Bundle;
4 | import android.text.TextUtils;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.EditText;
8 |
9 | import com.happyheng.sport_android.R;
10 | import com.happyheng.sport_android.model.request.BaseRequest;
11 | import com.happyheng.sport_android.model.request.RegisterRequest;
12 |
13 | /**
14 | * "注册"的Activity
15 | * Created by liuheng on 16/6/7.
16 | */
17 | public class RegisterActivity extends BaseActivity {
18 |
19 | private EditText mUserNameEt, mPassWordEt, mPassWordConfirmEt, mNickNameEt;
20 | private Button mRegisterBt;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_register);
26 |
27 | initView();
28 | }
29 |
30 | private void initView() {
31 | mUserNameEt = (EditText) findViewById(R.id.username_et);
32 | mPassWordEt = (EditText) findViewById(R.id.password_et);
33 | mPassWordConfirmEt = (EditText) findViewById(R.id.password_confirm_et);
34 | mNickNameEt = (EditText) findViewById(R.id.nickname_et);
35 |
36 | mRegisterBt = (Button) findViewById(R.id.register_bt);
37 | mRegisterBt.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View v) {
40 |
41 | String userName = mUserNameEt.getText().toString();
42 | String passWord = mPassWordEt.getText().toString();
43 | String passWordConfirm = mPassWordConfirmEt.getText().toString();
44 | String nickName = mNickNameEt.getText().toString();
45 |
46 | //进行判断,如果为空则弹出提示
47 | if (TextUtils.isEmpty(userName)) {
48 | showToast(getString(R.string.user_empty));
49 | } else if (TextUtils.isEmpty(passWord) || TextUtils.isEmpty(passWordConfirm)) {
50 | showToast(getString(R.string.pass_empty));
51 | } else if (!passWord.equals(passWordConfirm)) {
52 | showToast(getString(R.string.pass_wrong_confirm));
53 | } else if (TextUtils.isEmpty(nickName)) {
54 | showToast(getString(R.string.nick_empty));
55 | }
56 |
57 | BaseRequest request = new RegisterRequest(userName, passWord, nickName, new RegisterRequest.onRegisterListener() {
58 | @Override
59 | public void onSuccess() {
60 | showToast(getString(R.string.register_success));
61 | finish();
62 | }
63 |
64 | @Override
65 | public void onRepeatUserName() {
66 | showToast(getString(R.string.repeat_user_name));
67 | }
68 |
69 | @Override
70 | public void onRepeatNickName() {
71 | showToast(getString(R.string.repeat_nick));
72 | }
73 |
74 | @Override
75 | public void onFail() {
76 | showToast(getString(R.string.wrong_request));
77 | }
78 | });
79 | request.doRequest();
80 | }
81 | });
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/fragment/FragmentMine.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.fragment;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import com.happyheng.sport_android.R;
13 | import com.happyheng.sport_android.activity.ActivitySportList;
14 |
15 | /**
16 | * 主页面---我的
17 | * Created by liuheng on 16/7/14.
18 | */
19 | public class FragmentMine extends Fragment {
20 |
21 | private TextView mSportMessageTv;
22 |
23 | @Nullable
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
26 | return inflater.inflate(R.layout.fragment_mine,container,false);
27 | }
28 |
29 | @Override
30 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
31 | super.onViewCreated(view, savedInstanceState);
32 |
33 | mSportMessageTv = (TextView) view.findViewById(R.id.mine_sport_message_tv);
34 | mSportMessageTv.setOnClickListener(new View.OnClickListener() {
35 | @Override
36 | public void onClick(View v) {
37 | Intent intent = new Intent(getActivity(), ActivitySportList.class);
38 | startActivity(intent);
39 | }
40 | });
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/fragment/FragmentNews.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.fragment;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Rect;
5 | import android.support.v7.widget.RecyclerView;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.happyheng.sport_android.activity.ArticleActivity;
10 | import com.happyheng.sport_android.fragment.recycler.FragmentLoadRecycler;
11 | import com.happyheng.sport_android.model.News;
12 | import com.happyheng.sport_android.model.request.NewsRequest;
13 | import com.happyheng.sport_android.view.NewsItemView;
14 | import com.orhanobut.logger.Logger;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * 主页面---展示信息的Fragment
21 | * Created by liuheng on 16/7/14.
22 | */
23 | public class FragmentNews extends FragmentLoadRecycler {
24 |
25 | private List mNewsList = new ArrayList<>();
26 |
27 | private void OnItemClick(int position) {
28 | News news = mNewsList.get(position);
29 | String articleUrl = news.getUrl();
30 |
31 | Intent intent = new Intent(getActivity(), ArticleActivity.class);
32 | intent.putExtra(ArticleActivity.BUNDLE_URL, articleUrl);
33 | startActivity(intent);
34 | }
35 |
36 | @Override
37 | protected RequestResult requestDataInBackground(boolean isRefresh) {
38 |
39 | int begin;
40 | if (isRefresh) {
41 | begin = 0;
42 | } else {
43 | begin = mNewsList.size();
44 | }
45 |
46 | NewsRequest request = new NewsRequest();
47 | request.setBeginCount(begin, DEFAULT_REQUEST_COUNT);
48 | List resultList = request.getNewsItem();
49 |
50 | RequestResult result = new RequestResult();
51 | if (resultList != null) {
52 | mNewsList.addAll(resultList);
53 |
54 | result.ret = RequestResult.RET_SUCCESS;
55 | result.addCount = resultList.size();
56 | } else {
57 | result.ret = RequestResult.RET_FAILED;
58 | }
59 | return result;
60 | }
61 |
62 | @Override
63 | protected int getItemSize() {
64 | return mNewsList.size();
65 | }
66 |
67 | @Override
68 | protected void setItemOffset(Rect outRect, int position) {
69 | outRect.set(0, mDefaultTopDecoration, 0, 0);
70 | }
71 |
72 | @Override
73 | protected RecyclerView.ViewHolder getViewHolder(ViewGroup parent) {
74 | NewsItemView view = new NewsItemView(getContext(), null);
75 | return getBaseViewHolder(view);
76 | }
77 |
78 | @Override
79 | protected void bindingViewHolder(RecyclerView.ViewHolder holder, final int position) {
80 | NewsItemView itemView = (NewsItemView) holder.itemView;
81 | News news = mNewsList.get(position);
82 |
83 | itemView.setThumbnailSource(news.getThumbnail());
84 | itemView.setTitleString(news.getName());
85 | itemView.setContentString(news.getSimplecontent());
86 | itemView.setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View v) {
89 | OnItemClick(position);
90 | }
91 | });
92 | }
93 |
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/fragment/FragmentSport.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.fragment;
2 |
3 |
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v4.app.Fragment;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.Button;
12 |
13 | import com.happyheng.sport_android.R;
14 | import com.happyheng.sport_android.activity.MapActivity;
15 |
16 | /**
17 | * 主页面---运动的Fragment
18 | * Created by liuheng on 16/7/14.
19 | */
20 | public class FragmentSport extends Fragment implements View.OnClickListener{
21 |
22 | private Button mSportStartButton;
23 |
24 | @Nullable
25 | @Override
26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
27 | return inflater.inflate(R.layout.fragment_sport,container,false);
28 | }
29 |
30 |
31 | @Override
32 | public void onViewCreated(View view, Bundle savedInstanceState) {
33 | mSportStartButton = (Button) view.findViewById(R.id.tab_sport_start_bt);
34 |
35 | mSportStartButton.setOnClickListener(this);
36 | }
37 |
38 | @Override
39 | public void onClick(View v) {
40 | switch (v.getId()){
41 |
42 | //如果是开始运动的按钮
43 | case R.id.tab_sport_start_bt:
44 |
45 | Intent intent = new Intent(getActivity(), MapActivity.class);
46 | startActivity(intent);
47 | break;
48 |
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/fragment/recycler/FragmentBaseRecycler.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.fragment.recycler;
2 |
3 | import android.os.AsyncTask;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v4.widget.SwipeRefreshLayout;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.happyheng.sport_android.R;
14 |
15 |
16 | /**
17 | * 下拉刷新使用的RecyclerView的父类
18 | */
19 | public abstract class FragmentBaseRecycler
20 | extends Fragment
21 | {
22 | //默认还有多少item到底部时需要加载更多
23 | private static final int DEFAULT_RESET_ITEM_COUNT = 3;
24 |
25 | private View mContentView;
26 | private SwipeRefreshLayout mRefreshLayout;
27 | protected RecyclerView mRecyclerView;
28 |
29 | private RecyclerView.OnScrollListener mScrollListener = new ScrollListener();
30 | private SwipeRefreshLayout.OnRefreshListener mRefreshListener = new RefreshListener();
31 |
32 | protected boolean mIsInit = true;
33 | //是否正在请求的标志位
34 | private boolean mIsLoad = false;
35 | //是否有更多的标志位
36 | protected boolean mShouldLoad = true;
37 |
38 | @Nullable
39 | @Override
40 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle
41 | savedInstanceState)
42 | {
43 | if (mContentView == null)
44 | {
45 | mContentView = inflater.inflate(R.layout.fragment_base_recycler, container, false);
46 | mRefreshLayout = (SwipeRefreshLayout) mContentView.findViewById(R.id.refresh_layout);
47 | mRecyclerView = (RecyclerView) mContentView.findViewById(R.id.recycler_view);
48 |
49 | //设置是否下拉刷新
50 | mRefreshLayout.setEnabled(isRefreshEnable());
51 | if (isRefreshEnable())
52 | {
53 | mRefreshLayout.setRefreshing(true);
54 | }
55 | mRefreshLayout.setOnRefreshListener(mRefreshListener);
56 | mRecyclerView.addOnScrollListener(mScrollListener);
57 |
58 | //刚开始进入时,要进行刷新操作
59 | load(true);
60 | }
61 | else
62 | {
63 | mIsInit = false;
64 | }
65 | return mContentView;
66 | }
67 |
68 |
69 | //进行刷新的方法
70 | protected void refresh(boolean isShowSwipeRefreshView){
71 | if (isShowSwipeRefreshView){
72 | mRefreshLayout.setRefreshing(true);
73 | }
74 | load(true);
75 | }
76 |
77 | //从开始加载,或者从后面进行加载的方法
78 | protected void load(boolean isRefresh)
79 | {
80 | if (!mIsLoad)
81 | {
82 | LoadAsyncTask loadTask = new LoadAsyncTask(isRefresh);
83 | loadTask.execute();
84 | }
85 | }
86 |
87 |
88 | //SwipeRefreshLayout刷新的实现类
89 | private class RefreshListener
90 | implements SwipeRefreshLayout.OnRefreshListener
91 | {
92 |
93 | @Override
94 | public void onRefresh()
95 | {
96 | if (mIsLoad)
97 | {
98 | mRefreshLayout.setRefreshing(false);
99 | }
100 | else
101 | {
102 | load(true);
103 | }
104 |
105 | }
106 | }
107 |
108 | //RecyclerView滑动时回调的实现类
109 | private class ScrollListener
110 | extends RecyclerView.OnScrollListener
111 | {
112 | @Override
113 | public void onScrolled(RecyclerView recyclerView, int dx, int dy)
114 | {
115 | int lastVisibleItem = findLastVisibleItemPosition();
116 | int totalItemCount = recyclerView.getLayoutManager().getItemCount();
117 | //当距离底部小于约定数且有下一页时,才会进行刷新
118 | if (totalItemCount - lastVisibleItem <= DEFAULT_RESET_ITEM_COUNT && mShouldLoad)
119 | {
120 | load(false);
121 | }
122 | }
123 |
124 | @Override
125 | public void onScrollStateChanged(RecyclerView recyclerView, int newState)
126 | {
127 |
128 | }
129 | }
130 |
131 | /**
132 | * 设置SwipeRefreshLayout下拉刷新时结束的位置
133 | */
134 | protected void setSwipeRefreshEnd(int end){
135 | setSwipeRefreshStartAndEnd(0,end);
136 | }
137 |
138 | /**
139 | * 设置SwipeRefreshLayout下拉刷新时开始的位置和结束的位置
140 | */
141 | protected void setSwipeRefreshStartAndEnd(int start,int end){
142 | mRefreshLayout.setProgressViewOffset(false,start,end);
143 | }
144 |
145 | //每次都进行加载的AsyncTask
146 | protected class LoadAsyncTask
147 | extends AsyncTask
148 | {
149 |
150 | private boolean mIsRefresh;
151 |
152 | public LoadAsyncTask(boolean isRefresh)
153 | {
154 | this.mIsRefresh = isRefresh;
155 | }
156 |
157 |
158 | @Override
159 | protected RequestResult doInBackground(Void... params)
160 | {
161 | mIsLoad = true;
162 | return requestDataInBackground(mIsRefresh);
163 | }
164 |
165 | @Override
166 | protected void onPostExecute(RequestResult requestResult)
167 | {
168 |
169 | mIsLoad = false;
170 |
171 | //将mRefreshLayout消失
172 | mRefreshLayout.setRefreshing(false);
173 |
174 | if (requestResult != null && requestResult.ret == RequestResult.RET_SUCCESS && requestResult.addCount != 0)
175 | {
176 | mShouldLoad = true;
177 | }
178 | else
179 | {
180 | mShouldLoad = false;
181 | }
182 |
183 | //这个应该子类去实现
184 | onPostRequest(requestResult, mIsRefresh);
185 | }
186 | }
187 |
188 | public class RequestResult
189 | {
190 | public static final int RET_SUCCESS = 0;
191 | public static final int RET_FAILED = -1;
192 | public static final int ADD_COUNT_EMPTY = 0;
193 |
194 | public int ret = RET_FAILED;
195 | public int addCount = ADD_COUNT_EMPTY;
196 | }
197 |
198 |
199 | //子类需要实现的方法
200 | protected abstract RequestResult requestDataInBackground(boolean isRefresh);
201 |
202 | protected abstract void onPostRequest(RequestResult data, boolean refresh);
203 |
204 | protected abstract int findLastVisibleItemPosition();
205 |
206 |
207 | //子类来控制父类行为的方法
208 | // 是否可以下拉刷新
209 | protected boolean isRefreshEnable()
210 | {
211 | return true;
212 | }
213 |
214 | }
215 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/fragment/recycler/FragmentLoadRecycler.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.fragment.recycler;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Rect;
5 | import android.os.Bundle;
6 | import android.support.annotation.Nullable;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.happyheng.sport_android.R;
14 |
15 |
16 | /**
17 | * 继承自FragmentBaseRecycler,此类负责显示Load的判断以及LoadView的显示
18 | * 也对Adapter和ItemDecoration做出了简化,子类不在需要自定义Adapter,而是实现此类定义好的方法即可
19 | */
20 | public abstract class FragmentLoadRecycler
21 | extends FragmentBaseRecycler {
22 |
23 | //默认请求的数量
24 | protected static final int DEFAULT_REQUEST_COUNT = 10;
25 |
26 | protected LinearLayoutManager mLayoutManager;
27 | private RecyclerItemDecoration mDecoration;
28 | protected RecyclerView.Adapter mAdapter;
29 | //第一种为空View的类型,第二种为item的类型,第三种为footer的类型
30 | protected static final int TYPE_EMPTY = 0, TYPE_ITEM = 1, TYPE_FOOTER = 2;
31 | //默认的距离顶部的间距
32 | protected int mDefaultTopDecoration;
33 |
34 | //是否显示空View,使用此标志位的原因是使其刚开始加载的时候不显示空View,当首次加载成功后,以后才会显示
35 | protected boolean mIsShowEmptyView = false;
36 | //是否有默认的背景颜色,使用标志位的原因是子类可以选择不设置默认背景颜色来方式出现的过度绘制的问题
37 | private boolean mIsHadDefaultBack = true;
38 |
39 | @Override
40 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
41 | super.onViewCreated(view, savedInstanceState);
42 |
43 | if (mIsInit) {
44 | //1、设置分割线
45 | mDecoration = new RecyclerItemDecoration();
46 | mRecyclerView.addItemDecoration(mDecoration);
47 |
48 | //2、设置LayoutManager
49 | mLayoutManager = new LinearLayoutManager(getActivity());
50 | mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
51 | mRecyclerView.setLayoutManager(mLayoutManager);
52 |
53 | //3、设置Adapter(子类可以复写这个Adapter)
54 | mAdapter = new RecyclerAdapter();
55 | mRecyclerView.setAdapter(mAdapter);
56 |
57 | //得到默认距离顶部的间距
58 | mDefaultTopDecoration = getResources().getDimensionPixelSize(R.dimen.recycler_default_decoration_height);
59 | //设置背景颜色
60 | if (mIsHadDefaultBack) {
61 | mRecyclerView.setBackgroundColor(getResources().getColor(R.color.recycler_default_bg));
62 | }
63 | }
64 |
65 | }
66 |
67 | protected class RecyclerItemDecoration
68 | extends RecyclerView.ItemDecoration {
69 | @Override
70 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
71 | super.getItemOffsets(outRect, view, parent, state);
72 |
73 | int position = parent.getChildAdapterPosition(view);
74 | setItemOffset(outRect, position);
75 | }
76 |
77 |
78 | @Override
79 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
80 | super.onDraw(c, parent, state);
81 | }
82 | }
83 |
84 | @Override
85 | protected void onPostRequest(RequestResult data, boolean refresh) {
86 | mIsShowEmptyView = true;
87 |
88 | notifyDataSetChanged();
89 | }
90 |
91 | /**
92 | * 更新RecyclerView的方法
93 | */
94 | protected void notifyDataSetChanged() {
95 | if (mAdapter != null) {
96 | mAdapter.notifyDataSetChanged();
97 | }
98 | }
99 |
100 | protected RecyclerView.ViewHolder getBaseViewHolder(View itemView) {
101 | return new RecyclerView.ViewHolder(itemView) {
102 | };
103 | }
104 |
105 | public class RecyclerAdapter
106 | extends RecyclerView.Adapter {
107 |
108 | @Override
109 | public int getItemCount() {
110 | int num = getItemSize();
111 |
112 | //如果没有数据,那么应该显示EmptyView
113 | if (num == 0 && mIsShowEmptyView) {
114 | return 1;
115 | }
116 |
117 | if (mShouldLoad) {
118 | return num + 1;
119 | } else {
120 | return num;
121 | }
122 | }
123 |
124 | @Override
125 | public int getItemViewType(int position) {
126 |
127 | int num = getItemSize();
128 | if (num == 0) {
129 | return TYPE_EMPTY;
130 | }
131 |
132 | if (position == num) {
133 | return TYPE_FOOTER;
134 | } else {
135 | return TYPE_ITEM;
136 | }
137 | }
138 |
139 | @Override
140 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
141 |
142 | RecyclerView.ViewHolder holder;
143 |
144 | if (viewType == TYPE_EMPTY) {
145 |
146 | View mEmptyView = getEmptyView(parent);
147 | if (mEmptyView == null) {
148 | mEmptyView = getDefaultEmptyView(parent);
149 | }
150 |
151 | holder = getBaseViewHolder(mEmptyView);
152 | holder.itemView.setTag(TYPE_EMPTY);
153 | } else if (viewType == TYPE_ITEM) {
154 | //从子类中获取对应的Holder
155 | holder = getViewHolder(parent);
156 | RecyclerView.LayoutParams params = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
157 | ViewGroup.LayoutParams.WRAP_CONTENT);
158 | holder.itemView.setLayoutParams(params);
159 | holder.itemView.setTag(TYPE_ITEM);
160 | } else {
161 | View footerView = LayoutInflater.from(getActivity()).inflate(R.layout.item_load_more, parent,
162 | false);
163 | footerView.setTag(TYPE_FOOTER);
164 | holder = getBaseViewHolder(footerView);
165 | }
166 | return holder;
167 | }
168 |
169 | @Override
170 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
171 | if (holder.itemView.getTag() != null && (int) holder.itemView.getTag() == TYPE_ITEM) {
172 | //让子类去绑定数据源
173 | bindingViewHolder(holder, position);
174 | }
175 | }
176 |
177 | }
178 |
179 | /**
180 | * 得到默认的EmptyView的方法
181 | *
182 | * @param parent
183 | * @return
184 | */
185 | protected View getDefaultEmptyView(ViewGroup parent) {
186 | return new View(getActivity());
187 | }
188 |
189 | @Override
190 | protected int findLastVisibleItemPosition() {
191 | return mLayoutManager.findLastVisibleItemPosition();
192 | }
193 |
194 | protected RecyclerView.LayoutManager getLayoutManager() {
195 | return mLayoutManager;
196 | }
197 |
198 |
199 | //子类进行配置的方法
200 | //1、是否画默认的背景
201 | protected void hadDefaultBackColor(boolean hadDefaultBack) {
202 | this.mIsHadDefaultBack = hadDefaultBack;
203 | }
204 |
205 |
206 | // 子类必须要实现的方法
207 | // 1、得到要显示的item的大小(而不是得到数据源的大小,因为有的界面一个item会对应好几个数据源)
208 | protected abstract int getItemSize();
209 |
210 | // 2、得到item之间的间距
211 | protected abstract void setItemOffset(Rect outRect, int position);
212 |
213 | // 3、得到子类所对应的Item的ViewHolder
214 | protected abstract RecyclerView.ViewHolder getViewHolder(ViewGroup parent);
215 |
216 | // 4、设置子类所对应的Item的ViewHolder
217 | protected abstract void bindingViewHolder(RecyclerView.ViewHolder holder, int position);
218 |
219 | //得到空View,如果想换成其他的空View,子类可以复写这个方法
220 | public View getEmptyView(ViewGroup parent) {
221 | return null;
222 | }
223 |
224 | }
225 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/IdEntity.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model;
2 |
3 | public abstract class IdEntity {
4 | protected Long id;
5 |
6 | public Long getId() {
7 | return id;
8 | }
9 |
10 | public void setId(Long id) {
11 | this.id = id;
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/News.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model;
2 |
3 | public class News extends IdEntity {
4 | private String name;
5 | private String simplecontent;
6 | private String thumbnail;
7 | private String url;
8 | public String getName() {
9 | return name;
10 | }
11 | public void setName(String name) {
12 | this.name = name;
13 | }
14 | public String getSimplecontent() {
15 | return simplecontent;
16 | }
17 | public void setSimplecontent(String simplecontent) {
18 | this.simplecontent = simplecontent;
19 | }
20 | public String getThumbnail() {
21 | return thumbnail;
22 | }
23 | public void setThumbnail(String thumbnail) {
24 | this.thumbnail = thumbnail;
25 | }
26 | public String getUrl() {
27 | return url;
28 | }
29 | public void setUrl(String url) {
30 | this.url = url;
31 | }
32 |
33 | @Override
34 | public String toString() {
35 | return "News{" +
36 | "name='" + name + '\'' +
37 | ", simplecontent='" + simplecontent + '\'' +
38 | ", thumbnail='" + thumbnail + '\'' +
39 | ", url='" + url + '\'' +
40 | '}';
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/User.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model;
2 |
3 | import android.content.Context;
4 | import android.text.TextUtils;
5 |
6 | import com.happyheng.sport_android.utils.SPUtils;
7 |
8 | /**
9 | * User类封装了用户操作的一系列信息
10 | * Created by liuheng on 16/6/13.
11 | */
12 | public class User {
13 |
14 | //储存用户token的key
15 | private static final String TOKEN_KEY = "token";
16 | private static User defaultUser;
17 |
18 | private Context mContext;
19 |
20 | /**
21 | * 初始化单例User对象
22 | * @param context
23 | */
24 | public static void init(Context context){
25 | if (defaultUser == null){
26 | defaultUser = new User(context);
27 | }
28 | }
29 |
30 | /**
31 | * 得到单例对象
32 | * @return
33 | */
34 | public static User getUser(){
35 | return defaultUser;
36 | }
37 |
38 |
39 | private User(Context context){
40 | this.mContext = context;
41 | }
42 |
43 | /**
44 | * 得到用户是否登录的方法
45 | * @return
46 | */
47 | public boolean isUserLogin(){
48 | String token = getUserToken();
49 | return !TextUtils.isEmpty(token);
50 | }
51 |
52 |
53 | /**
54 | * 设置User的Token
55 | *
56 | * @param token
57 | */
58 | public void setUserToken(String token) {
59 | SPUtils.put(mContext, TOKEN_KEY, token);
60 | }
61 |
62 |
63 | /**
64 | * 得到User的Token
65 | * @return
66 | */
67 | public String getUserToken(){
68 | return (String) SPUtils.get(mContext,TOKEN_KEY,"");
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/BaseResult.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 | /**
4 | * 所有返回的数据的基类
5 | * Created by liuheng on 16/7/7.
6 | */
7 | public class BaseResult {
8 | private int result;
9 |
10 | public int getResult() {
11 | return result;
12 | }
13 |
14 | public void setResult(int result) {
15 | this.result = result;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/Location.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 | public class Location {
4 |
5 | private double posx;
6 | private double posy;
7 |
8 | public double getPosx() {
9 | return posx;
10 | }
11 |
12 | public void setPosx(double posx) {
13 | this.posx = posx;
14 | }
15 |
16 | public double getPosy() {
17 | return posy;
18 | }
19 |
20 | public void setPosy(double posy) {
21 | this.posy = posy;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/NewsResult.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 |
4 | import com.happyheng.sport_android.model.News;
5 |
6 | import java.util.List;
7 |
8 | public class NewsResult {
9 | private int code;
10 | private List data;
11 |
12 |
13 | public int getCode() {
14 | return code;
15 | }
16 | public void setCode(int code) {
17 | this.code = code;
18 | }
19 | public List getData() {
20 | return data;
21 | }
22 | public void setData(List data) {
23 | this.data = data;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/PostRequestBody.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 | /**
4 | * 在Post请求中的将key-value封装的类
5 | * Created by liuheng on 16/6/11.
6 | */
7 | public class PostRequestBody {
8 | public String name;
9 | public String value;
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/SportListResult.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 | import java.util.List;
4 |
5 |
6 | public class SportListResult {
7 | private int result;
8 | private List data;
9 |
10 |
11 | public int getResult() {
12 | return result;
13 | }
14 | public void setResult(int result) {
15 | this.result = result;
16 | }
17 | public List getData() {
18 | return data;
19 | }
20 | public void setData(List data) {
21 | this.data = data;
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/entity/SportMessageResult.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.entity;
2 |
3 | import java.util.List;
4 |
5 |
6 | public class SportMessageResult {
7 |
8 | private int result;
9 | private List data;
10 |
11 | public int getResult() {
12 | return result;
13 | }
14 | public void setResult(int result) {
15 | this.result = result;
16 | }
17 | public List getData() {
18 | return data;
19 | }
20 | public void setData(List data) {
21 | this.data = data;
22 | }
23 |
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/event/LocationEvent.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.event;
2 |
3 | import com.baidu.mapapi.model.LatLng;
4 |
5 | /**
6 | * 定位的Event
7 | * Created by liuheng on 16/7/24.
8 | */
9 | public class LocationEvent {
10 |
11 | private LatLng location;
12 |
13 | public LocationEvent(LatLng location) {
14 | this.location = location;
15 | }
16 |
17 | public LatLng getLocation() {
18 | return location;
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/network/HttpClient.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.network;
2 |
3 | import android.content.Context;
4 |
5 | import com.happyheng.sport_android.model.entity.PostRequestBody;
6 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
7 | import com.happyheng.sport_android.utils.ThreadUtils;
8 | import com.orhanobut.logger.Logger;
9 |
10 | import java.io.IOException;
11 | import java.io.UnsupportedEncodingException;
12 |
13 | import okhttp3.Cache;
14 | import okhttp3.Call;
15 | import okhttp3.Callback;
16 | import okhttp3.OkHttpClient;
17 | import okhttp3.Request;
18 | import okhttp3.Response;
19 |
20 | /**
21 | * 基于"Okhttp"的网络访问工具类
22 | * 注意在所有的请求中,都会有请求对应的路径名,和对应的键值对,需要把键值对序列化成json,然后请求时让s对应此json。这样是为了
23 | * 将数据加密
24 | * Created by liuheng on 2016/6/7.
25 | */
26 | public class HttpClient {
27 |
28 | private static final int CacheSize = 50 * 1024 * 1024; // 缓存的大小,默认为50 MiB
29 | private static final String DEFAULT_NULL_RESULT = ""; //默认的空返回值
30 |
31 |
32 | private static OkHttpClient mOkHttpClient = null;
33 |
34 |
35 | public enum CacheControl {
36 | //先从缓存中取,如果没有,在从网络上去取
37 | CacheElseNetwork,
38 | //只从网络中去取
39 | Network
40 | }
41 |
42 | /**
43 | * 初始化请求工具类的方法
44 | */
45 | public static void init(Context context) {
46 | //写到缓存下的子目录下,方便统一管理
47 | Cache cache = new Cache(context.getExternalCacheDir(), CacheSize);
48 | if (mOkHttpClient == null) {
49 | mOkHttpClient = new OkHttpClient.Builder()
50 | .cache(cache)
51 | .build();
52 | }
53 |
54 | }
55 |
56 |
57 | /**
58 | * 同步从网络上获取数据
59 | *
60 | * @param url 请求的url
61 | * @param bodys 此为请求的键值对数组
62 | * @return 返回请求的json字符串,如果失败,返回""
63 | */
64 | public static String doSyncPost(String url, PostRequestBody[] bodys) {
65 |
66 | Request request;
67 | try {
68 | request = HttpClientRequestHelper.getRequest(url, bodys, okhttp3.CacheControl.FORCE_NETWORK);
69 | Response response = mOkHttpClient.newCall(request).execute();
70 |
71 | if (response.isSuccessful()) {
72 |
73 | return response.body().string();
74 | } else {
75 | Logger.d("请求失败");
76 | }
77 | } catch (Exception e) {
78 | e.printStackTrace();
79 | }
80 |
81 | return DEFAULT_NULL_RESULT;
82 | }
83 |
84 |
85 | /**
86 | * 异步去网络上请求数据的方法
87 | *
88 | * @param url 请求的url
89 | * @param bodys 此为请求的键值对数组
90 | * @param requestListener 请求回调的接口 两种情况:
91 | * 请求完全成功后,才会调用onSuccess()方法,其它调用onFail()方法
92 | */
93 | public static void doAsyncPost(String url, PostRequestBody[] bodys, final OnRequestListener requestListener) {
94 | final Request request;
95 | try {
96 | request = HttpClientRequestHelper.getRequest(url, bodys, okhttp3.CacheControl.FORCE_NETWORK);
97 |
98 | mOkHttpClient.newCall(request).enqueue(new Callback() {
99 |
100 | @Override
101 | public void onResponse(Call call, final Response response) throws IOException {
102 |
103 |
104 | try {
105 | if (response.isSuccessful()) {
106 |
107 | final String result = response.body().string();
108 | ThreadUtils.runOnMainThread(new Runnable() {
109 | @Override
110 | public void run() {
111 | requestListener.onSuccess(result);
112 | }
113 | });
114 |
115 | }
116 | //在这里失败,即为返回的code不在200-300之间,意思即为服务器出现的错误,这种情况很少出现,但视为网络错误
117 | else {
118 | ThreadUtils.runOnMainThread(new Runnable() {
119 | @Override
120 | public void run() {
121 | requestListener.onFail();
122 | }
123 | });
124 | }
125 |
126 | } catch (IOException e) {
127 | e.printStackTrace();
128 | ThreadUtils.runOnMainThread(new Runnable() {
129 | @Override
130 | public void run() {
131 | requestListener.onFail();
132 | }
133 | });
134 | }
135 | }
136 |
137 | //一般来说,如果是失败的话,一般都为网络异常,比如手机未联网等
138 | @Override
139 | public void onFailure(Call call, IOException e) {
140 | ThreadUtils.runOnMainThread(new Runnable() {
141 | @Override
142 | public void run() {
143 | requestListener.onFail();
144 | }
145 | });
146 | }
147 | });
148 | } catch (UnsupportedEncodingException e) {
149 | e.printStackTrace();
150 | requestListener.onFail();
151 | }
152 |
153 | }
154 |
155 |
156 | /**
157 | * 提供"缓存"的异步方法,具体的缓存方法为:
158 | *
159 | * 1、先从本地去取缓存,取到缓存后,先回调成功接口,然后走下一步,如果没有取到缓存,直接走下一步
160 | * 2、不管取没取到,都会从网络取新的数据,如果失败,回调失败接口。如果成功,回调成功接口。
161 | */
162 |
163 |
164 | /**
165 | * 根据请求的数据等来获取Okhttp中的Request请求对象
166 | */
167 | // private static Request getRequest(String path, String requestString, okhttp3.CacheControl cacheControl) throws UnsupportedEncodingException {
168 | //
169 | // String encoderRequestString = URLEncoder.encode(requestString, "UTF8");
170 | //
171 | // RequestBody requestBody = new FormBody.Builder()
172 | // .add("s", encoderRequestString)
173 | // .build();
174 | //
175 | // return new Request.Builder()
176 | // .url(BASE_URL + path)
177 | // .post(requestBody)
178 | // .cacheControl(cacheControl)
179 | // .build();
180 | // }
181 |
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/network/HttpClientRequestHelper.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.network;
2 |
3 | import com.happyheng.sport_android.model.entity.PostRequestBody;
4 |
5 | import java.io.UnsupportedEncodingException;
6 | import java.net.URLEncoder;
7 |
8 | import okhttp3.FormBody;
9 | import okhttp3.Request;
10 | import okhttp3.RequestBody;
11 |
12 | /**
13 | * 获取HttpClient中Request请求对象的帮助类
14 | * Created by liuheng on 16/6/11.
15 | */
16 | public class HttpClientRequestHelper {
17 |
18 | public static Request getRequest(String url, PostRequestBody[] bodys, okhttp3.CacheControl cacheControl) throws UnsupportedEncodingException {
19 |
20 | FormBody.Builder builder = new FormBody.Builder();
21 | for (PostRequestBody body : bodys) {
22 | //请求的value要经过编码
23 | //String encoderRequestString = URLEncoder.encode(body.value, "UTF8");
24 | builder.add(body.name, body.value);
25 | }
26 |
27 | RequestBody requestBody = builder.build();
28 |
29 | return new Request.Builder()
30 | .url(url)
31 | .post(requestBody)
32 | .cacheControl(cacheControl)
33 | .build();
34 | }
35 |
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/network/listener/OnRequestListener.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.network.listener;
2 |
3 | /**
4 | * 异步请求的接口
5 | * Created by liuheng on 2016/6/7.
6 | */
7 | public interface OnRequestListener{
8 | void onSuccess(T t);
9 | void onFail();
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/BaseRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.happyheng.sport_android.model.entity.PostRequestBody;
4 | import com.happyheng.sport_android.model.network.HttpClient;
5 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
6 | import com.happyheng.sport_android.utils.AESUtils;
7 | import com.happyheng.sport_android.utils.HexUtils;
8 |
9 |
10 | /**
11 | * Request请求的基类,封装了错误码,网络访问的方法
12 | * 子类需要实现HttpClient请求的回调,即获取到返回值,并根据不同的请求作出处理,在写出相应请求的回调。
13 | * Created by liuheng on 16/6/11.
14 | */
15 | public abstract class BaseRequest {
16 |
17 | private static final String HEX_KEY = "5de7e29919fad4d5a17f97a3b6215a68";
18 | private static final byte[] key = HexUtils.hexStringToBytes(HEX_KEY);
19 |
20 | //private static final String DOMAIN_NAME = "www.happyheng.top";
21 | private static final String DOMAIN_NAME = "192.168.1.4";
22 | private static final String BASE_URL = "http://"+ DOMAIN_NAME +":8080/Sport/";
23 | private static final String REQUEST_BASE_KEY = "s";
24 | protected static final String RESULT_KEY = "result";
25 |
26 | public static final int REQUEST_SUCCESS = 0; //成功
27 | public static final int REQUEST_OTHER_EXCEPTION = 100; //服务器错误,请求错误等等非逻辑错误,都是这个
28 |
29 | public void doRequest(){
30 | String path = BASE_URL+getRequestPath();
31 |
32 | PostRequestBody body = new PostRequestBody();
33 | body.name = REQUEST_BASE_KEY;
34 | body.value = AESUtils.encrypt(key,getRequestJsonString());
35 |
36 | HttpClient.doAsyncPost(path,new PostRequestBody[]{body}, getRequestListener());
37 | }
38 |
39 | public String doSyncPost(){
40 | String path = BASE_URL+getRequestPath();
41 |
42 | PostRequestBody body = new PostRequestBody();
43 | body.name = REQUEST_BASE_KEY;
44 | body.value = AESUtils.encrypt(key,getRequestJsonString());
45 |
46 | return HttpClient.doSyncPost(path,new PostRequestBody[]{body});
47 | }
48 |
49 |
50 | /**
51 | * 得到HttpClient请求的回调接口
52 | * @return 请求回调
53 | */
54 | protected abstract OnRequestListener getRequestListener();
55 |
56 | /**
57 | * 得到请求的path
58 | * @return
59 | */
60 | protected abstract String getRequestPath();
61 |
62 | /**
63 | * 得到封装的请求json数据
64 | * @return
65 | */
66 | protected abstract String getRequestJsonString();
67 |
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/LoginRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
6 |
7 | /**
8 | * 登陆请求的类
9 | * Created by liuheng on 16/6/8.
10 | */
11 | public class LoginRequest extends BaseRequest{
12 |
13 | public static final int REQUEST_WRONG_USERNAME = 1; //没有相应用户名
14 | public static final int REQUEST_WRONG_PASSWORD = 2; //密码错误
15 |
16 | public static final String REQUEST_PATH = "Login";
17 |
18 | //登陆的用户名和密码
19 | private String userName,password;
20 | private OnLoginListener listener;
21 |
22 | public LoginRequest(String userName, String password, OnLoginListener listener) {
23 | this.userName = userName;
24 | this.password = password;
25 | this.listener = listener;
26 | }
27 |
28 | @Override
29 | protected String getRequestPath() {
30 | return REQUEST_PATH;
31 | }
32 |
33 | @Override
34 | protected String getRequestJsonString() {
35 | JSONObject jsonObject = new JSONObject();
36 | jsonObject.put("uname", userName);
37 | jsonObject.put("upwd", password);
38 | return jsonObject.toString();
39 | }
40 |
41 | @Override
42 | protected OnRequestListener getRequestListener() {
43 | return new OnRequestListener() {
44 | @Override
45 | public void onSuccess(String s) {
46 |
47 | if (listener != null){
48 | JSONObject resultJson = JSON.parseObject(s);
49 | int code = resultJson.getInteger(RESULT_KEY);
50 | if (code == REQUEST_SUCCESS) {
51 | String token = resultJson.getJSONObject("data").getString("token");
52 | listener.onSuccess(token);
53 | } else {
54 | listener.onFail(code);
55 | }
56 | }
57 |
58 | }
59 |
60 | @Override
61 | public void onFail() {
62 | if (listener!=null){
63 | listener.onFail(REQUEST_OTHER_EXCEPTION);
64 | }
65 | }
66 | };
67 | }
68 |
69 | public interface OnLoginListener {
70 | void onSuccess(String token);
71 |
72 | void onFail(int code);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/NewsRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import android.text.TextUtils;
4 |
5 | import com.alibaba.fastjson.JSON;
6 | import com.alibaba.fastjson.JSONObject;
7 | import com.happyheng.sport_android.model.News;
8 | import com.happyheng.sport_android.model.entity.NewsResult;
9 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
10 | import com.orhanobut.logger.Logger;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * '发现频道'的请求类
16 | * Created by liuheng on 16/7/20.
17 | */
18 | public class NewsRequest extends BaseRequest {
19 |
20 | public static final String REQUEST_PATH = "News";
21 | public static final int DEFAULT_VALUE = -1;
22 |
23 | private int mBeginPosition = DEFAULT_VALUE, mId = DEFAULT_VALUE, mCount;
24 |
25 | public void setBeginCount(int beginPosition, int count) {
26 | this.mBeginPosition = beginPosition;
27 | this.mCount = count;
28 | }
29 |
30 | public void setIdCount(int id, int count) {
31 | this.mId = id;
32 | this.mCount = count;
33 | }
34 |
35 |
36 | /**
37 | * 通过获取新闻数据源的方法
38 | * @return
39 | */
40 | public List getNewsItem() {
41 |
42 | //进行同步请求
43 | String resultJson = doSyncPost();
44 |
45 | if (!TextUtils.isEmpty(resultJson)){
46 | NewsResult result = JSON.parseObject(resultJson, NewsResult.class);
47 | if (result != null && result.getCode() == REQUEST_SUCCESS) {
48 | return result.getData();
49 | } else {
50 | return null;
51 | }
52 | } else {
53 | return null;
54 | }
55 |
56 | }
57 |
58 | @Override
59 | protected OnRequestListener getRequestListener() {
60 | return new OnRequestListener() {
61 | @Override
62 | public void onSuccess(String s) {
63 |
64 | if (mNewsListener != null) {
65 | NewsResult result = JSON.parseObject(s, NewsResult.class);
66 |
67 | if (result != null && result.getCode() == REQUEST_SUCCESS) {
68 | mNewsListener.onSuccess(result.getData());
69 | } else {
70 | mNewsListener.onFail();
71 | }
72 | }
73 |
74 | }
75 |
76 | @Override
77 | public void onFail() {
78 | if (mNewsListener != null) {
79 | mNewsListener.onFail();
80 | }
81 | }
82 | };
83 | }
84 |
85 |
86 | @Override
87 | protected String getRequestPath() {
88 | return REQUEST_PATH;
89 | }
90 |
91 | @Override
92 | protected String getRequestJsonString() {
93 |
94 | JSONObject jsonObject = new JSONObject();
95 | if (mId == DEFAULT_VALUE) {
96 | jsonObject.put("begin", mBeginPosition);
97 | } else {
98 | jsonObject.put("id", mId);
99 | }
100 | jsonObject.put("count", mCount);
101 |
102 | return jsonObject.toString();
103 | }
104 |
105 | public interface OnNewsListener {
106 | void onSuccess(List list);
107 |
108 | void onFail();
109 | }
110 |
111 | private OnNewsListener mNewsListener;
112 |
113 | public void setNewsListener(OnNewsListener newsListener) {
114 | this.mNewsListener = newsListener;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/RecordSportMessageRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.entity.BaseResult;
6 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
7 |
8 | /**
9 | * 上传用户运动信息的Request
10 | * Created by liuheng on 16/7/7.
11 | */
12 | public class RecordSportMessageRequest extends BaseRequest{
13 |
14 | public static final String REQUEST_PATH = "Record";
15 | //需要上传的运动信息
16 | public SportMessage mMessage;
17 |
18 | public void setMessage(SportMessage message){
19 | this.mMessage = message;
20 | }
21 |
22 | @Override
23 | protected OnRequestListener getRequestListener() {
24 | return new OnRequestListener() {
25 | @Override
26 | public void onSuccess(String s) {
27 | if (mRecordListener != null){
28 | BaseResult result = JSONObject.parseObject(s,BaseResult.class);
29 | if (result.getResult() == REQUEST_SUCCESS){
30 | mRecordListener.onSuccess();
31 | } else {
32 | mRecordListener.onFail();
33 | }
34 | }
35 | }
36 |
37 | @Override
38 | public void onFail() {
39 | if (mRecordListener != null){
40 | mRecordListener.onFail();
41 | }
42 | }
43 | };
44 | }
45 |
46 | @Override
47 | protected String getRequestPath() {
48 | return REQUEST_PATH;
49 | }
50 |
51 | @Override
52 | protected String getRequestJsonString() {
53 | if (mMessage!=null){
54 | return JSON.toJSONString(mMessage);
55 | } else {
56 | return null;
57 | }
58 | }
59 |
60 | /**
61 | * 封装了上传至服务器运动信息的类
62 | */
63 | public static class SportMessage{
64 | public int id;
65 | public double posx;
66 | public double posy;
67 | public String location;
68 |
69 | public SportMessage(){}
70 |
71 | public SportMessage(int id, double posx, double posy, String location) {
72 | this.id = id;
73 | this.posx = posx;
74 | this.posy = posy;
75 | this.location = location;
76 | }
77 |
78 | public int getId() {
79 | return id;
80 | }
81 |
82 | public void setId(int id) {
83 | this.id = id;
84 | }
85 |
86 | public double getPosx() {
87 | return posx;
88 | }
89 |
90 | public void setPosx(double posx) {
91 | this.posx = posx;
92 | }
93 |
94 | public double getPosy() {
95 | return posy;
96 | }
97 |
98 | public void setPosy(double posy) {
99 | this.posy = posy;
100 | }
101 |
102 | public String getLocation() {
103 | return location;
104 | }
105 |
106 | public void setLocation(String location) {
107 | this.location = location;
108 | }
109 | }
110 |
111 | public interface OnRecordListener{
112 | void onSuccess();
113 | void onFail();
114 | }
115 |
116 | private OnRecordListener mRecordListener;
117 |
118 | public void setRecordListener(OnRecordListener listener){
119 | this.mRecordListener = listener;
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/RegisterRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
6 |
7 | /**
8 | * 注册请求的类
9 | * Created by liuheng on 16/6/25.
10 | */
11 | public class RegisterRequest extends BaseRequest {
12 |
13 | private String mUserName, mPassWord, mNickName;
14 | private onRegisterListener mListener;
15 |
16 | public static final String REQUEST_PATH = "Register";
17 |
18 | //重复用户名
19 | public static final int REQUEST_REPEAT_USERNAME = 1;
20 | //重复昵称
21 | public static final int REQUEST_REPEAT_NICKNAME = 2;
22 |
23 | public RegisterRequest(String userName, String passWord, String nickName, onRegisterListener listener) {
24 | this.mUserName = userName;
25 | this.mPassWord = passWord;
26 | this.mNickName = nickName;
27 | this.mListener = listener;
28 | }
29 |
30 | @Override
31 | protected OnRequestListener getRequestListener() {
32 | return new OnRequestListener() {
33 | @Override
34 | public void onSuccess(String s) {
35 | JSONObject resultJson = JSON.parseObject(s);
36 | int code = resultJson.getInteger(RESULT_KEY);
37 |
38 | //根据不同的code,回调不同的接口的方法
39 | if (code == REQUEST_SUCCESS) {
40 | mListener.onSuccess();
41 | } else if (code == REQUEST_REPEAT_USERNAME) {
42 | mListener.onRepeatUserName();
43 | } else if (code == REQUEST_REPEAT_NICKNAME) {
44 | mListener.onRepeatNickName();
45 | } else {
46 | mListener.onFail();
47 | }
48 | }
49 |
50 | @Override
51 | public void onFail() {
52 | mListener.onFail();
53 | }
54 | };
55 | }
56 |
57 | @Override
58 | protected String getRequestPath() {
59 | return REQUEST_PATH;
60 | }
61 |
62 | @Override
63 | protected String getRequestJsonString() {
64 | JSONObject jsonObject = new JSONObject();
65 | jsonObject.put("uname", mUserName);
66 | jsonObject.put("upwd", mPassWord);
67 | jsonObject.put("nkname", mNickName);
68 | return jsonObject.toJSONString();
69 | }
70 |
71 | public interface onRegisterListener {
72 | void onSuccess();
73 |
74 | void onRepeatUserName();
75 |
76 | void onRepeatNickName();
77 |
78 | void onFail();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/SportIdRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.User;
6 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
7 |
8 | /**
9 | * 得到运动id的Request
10 | * Created by liuheng on 16/7/5.
11 | */
12 | public class SportIdRequest extends BaseRequest{
13 |
14 |
15 | private OnSportIdListener mSportIdListener;
16 |
17 | public SportIdRequest(OnSportIdListener sportIdListener){
18 | this.mSportIdListener = sportIdListener;
19 | }
20 |
21 |
22 | @Override
23 | protected OnRequestListener getRequestListener() {
24 | return new OnRequestListener() {
25 | @Override
26 | public void onSuccess(String s) {
27 | if (mSportIdListener != null) {
28 | JSONObject resultJson = JSON.parseObject(s);
29 | int code = resultJson.getIntValue(RESULT_KEY);
30 |
31 | if (code == REQUEST_SUCCESS) {
32 | mSportIdListener.onSuccess(resultJson.getIntValue("id"));
33 | }else {
34 | mSportIdListener.onFail();
35 | }
36 | }
37 | }
38 |
39 | @Override
40 | public void onFail() {
41 | if (mSportIdListener != null) {
42 | mSportIdListener.onFail();
43 | }
44 | }
45 | };
46 | }
47 |
48 | @Override
49 | protected String getRequestPath() {
50 | return "SportId";
51 | }
52 |
53 | @Override
54 | protected String getRequestJsonString() {
55 | JSONObject jsonObject = new JSONObject();
56 | jsonObject.put("ukey", User.getUser().getUserToken());
57 | return jsonObject.toString();
58 | }
59 |
60 | public interface OnSportIdListener {
61 | void onSuccess(int sportId);
62 | void onFail();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/SportListRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.entity.SportListResult;
6 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | * 请求Sport信息的Request
12 | * Created by liuheng on 16/8/15.
13 | */
14 | public class SportListRequest extends BaseRequest {
15 |
16 | private String mUserKey;
17 |
18 | public SportListRequest(String userKey) {
19 | this.mUserKey = userKey;
20 | }
21 |
22 | @Override
23 | protected OnRequestListener getRequestListener() {
24 | return new OnRequestListener() {
25 | @Override
26 | public void onSuccess(String s) {
27 | if (listener!=null){
28 | SportListResult result = JSON.parseObject(s,SportListResult.class);
29 |
30 | if (result != null && result.getResult() != REQUEST_OTHER_EXCEPTION){
31 | listener.onSuccess(result.getData());
32 | } else {
33 | listener.onFail();
34 | }
35 | }
36 | }
37 |
38 | @Override
39 | public void onFail() {
40 | if (listener!=null){
41 | listener.onFail();
42 | }
43 | }
44 | };
45 | }
46 |
47 | @Override
48 | protected String getRequestPath() {
49 | return "SportList";
50 | }
51 |
52 | @Override
53 | protected String getRequestJsonString() {
54 |
55 | JSONObject jsonObject = new JSONObject();
56 | jsonObject.put("userkey", mUserKey);
57 | return jsonObject.toString();
58 | }
59 |
60 | public interface ListListener{
61 | void onSuccess(List list);
62 | void onFail();
63 | }
64 |
65 | private ListListener listener;
66 |
67 | public void setListListener(ListListener listener){
68 | this.listener = listener;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/model/request/SportMessageRequest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.model.request;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.happyheng.sport_android.model.entity.Location;
6 | import com.happyheng.sport_android.model.entity.SportMessageResult;
7 | import com.happyheng.sport_android.model.network.listener.OnRequestListener;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * 请求详细运动数据的Request
13 | * Created by liuheng on 16/8/16.
14 | */
15 | public class SportMessageRequest extends BaseRequest {
16 |
17 |
18 | private String userKey, sportId;
19 |
20 | public SportMessageRequest(String userKey, String sportId) {
21 | this.userKey = userKey;
22 | this.sportId = sportId;
23 | }
24 |
25 | @Override
26 | protected OnRequestListener getRequestListener() {
27 | return new OnRequestListener() {
28 | @Override
29 | public void onSuccess(String s) {
30 |
31 | if (messageListener != null) {
32 |
33 | SportMessageResult result = JSON.parseObject(s, SportMessageResult.class);
34 | if (result != null && result.getResult() != REQUEST_OTHER_EXCEPTION) {
35 | messageListener.onSuccess(result.getData());
36 | } else {
37 | messageListener.onFail();
38 | }
39 | }
40 |
41 | }
42 |
43 | @Override
44 | public void onFail() {
45 | if (messageListener != null) {
46 | messageListener.onFail();
47 | }
48 | }
49 | };
50 | }
51 |
52 | public interface OnSportMessageListener {
53 | void onSuccess(List data);
54 |
55 | void onFail();
56 | }
57 |
58 | private OnSportMessageListener messageListener;
59 |
60 | public void setMessageListener(OnSportMessageListener listener) {
61 | this.messageListener = listener;
62 | }
63 |
64 | @Override
65 | protected String getRequestPath() {
66 | return "SportMessage";
67 | }
68 |
69 | @Override
70 | protected String getRequestJsonString() {
71 | JSONObject jsonObject = new JSONObject();
72 | jsonObject.put("userkey", userKey);
73 | jsonObject.put("sportId", sportId);
74 | return jsonObject.toString();
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/service/LocationService.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.service;
2 |
3 | import android.app.Service;
4 | import android.content.Intent;
5 | import android.os.IBinder;
6 | import android.support.annotation.Nullable;
7 |
8 | import com.baidu.location.BDLocation;
9 | import com.baidu.location.BDLocationListener;
10 | import com.baidu.location.LocationClient;
11 | import com.baidu.location.LocationClientOption;
12 | import com.baidu.mapapi.model.LatLng;
13 | import com.happyheng.sport_android.model.event.LocationEvent;
14 | import com.happyheng.sport_android.servicecode.RecordService;
15 | import com.happyheng.sport_android.servicecode.impl.RecordServiceImpl;
16 | import com.orhanobut.logger.Logger;
17 |
18 | import org.greenrobot.eventbus.EventBus;
19 |
20 | import java.util.LinkedList;
21 | import java.util.List;
22 |
23 | /**
24 | * 定位的Service类,用户在运动时此服务会在后台进行定位。
25 | * Created by liuheng on 16/7/24.
26 | */
27 | public class LocationService extends Service implements BDLocationListener {
28 |
29 | //定位的时间间隔,单位是毫秒
30 | private static final int LOCATION_SPAN = 10 * 1000;
31 |
32 | //百度地图中定位的类
33 | public LocationClient mLocationClient = null;
34 | //记录着运动中移动的坐标位置
35 | private List mSportLatLngs = new LinkedList<>();
36 |
37 | //记录运动信息的Service
38 | private RecordService mRecordService = null;
39 |
40 | @Override
41 | public void onCreate() {
42 |
43 | //声明LocationClient类
44 | mLocationClient = new LocationClient(getApplicationContext());
45 | //给定位类加入自定义的配置
46 | initLocationOption();
47 | //注册监听函数
48 | mLocationClient.registerLocationListener(this);
49 |
50 | //初始化信息记录类
51 | mRecordService = new RecordServiceImpl(this);
52 |
53 | //开始监听
54 | mLocationClient.start();
55 | }
56 |
57 | //初始化定位的配置
58 | private void initLocationOption() {
59 | LocationClientOption option = new LocationClientOption();
60 | option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy
61 | );//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
62 | option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系
63 | option.setScanSpan(LOCATION_SPAN);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
64 | option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
65 | option.setOpenGps(true);//可选,默认false,设置是否使用gps
66 | option.setLocationNotify(false);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
67 | option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
68 | option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
69 | option.setIgnoreKillProcess(true);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
70 | option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
71 | option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
72 | mLocationClient.setLocOption(option);
73 | }
74 |
75 | //获取经纬度后回调的方法
76 | @Override
77 | public void onReceiveLocation(BDLocation bdLocation) {
78 | //先暂时获得经纬度信息,并将其记录在List中
79 | Logger.d("纬度信息为" + bdLocation.getLatitude()+"\n经度信息为" + bdLocation.getLongitude());
80 | LatLng locationValue = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
81 | mSportLatLngs.add(locationValue);
82 |
83 | //将运动信息上传至服务器
84 | recordLocation(locationValue,bdLocation.getLocationDescribe());
85 |
86 | //定位成功,发送定位Event通知
87 | EventBus.getDefault().post(new LocationEvent(locationValue));
88 | }
89 |
90 |
91 | private void recordLocation(LatLng latLng, String location) {
92 | if (mRecordService != null) {
93 | mRecordService.recordSport(latLng, location);
94 | }
95 | }
96 |
97 | @Nullable
98 | @Override
99 | public IBinder onBind(Intent intent) {
100 | return null;
101 | }
102 |
103 | @Override
104 | public void onDestroy() {
105 | super.onDestroy();
106 | mLocationClient.stop();
107 | mLocationClient.unRegisterLocationListener(this);
108 | Logger.d("onDestroy");
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/servicecode/RecordService.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.servicecode;
2 |
3 | import com.baidu.mapapi.model.LatLng;
4 |
5 | /**
6 | * 上传跑步信息的Service接口
7 | * Created by liuheng on 16/7/3.
8 | */
9 | public interface RecordService {
10 |
11 | //记录运动坐标和大概描述信息
12 | void recordSport(LatLng latLng,String location);
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/servicecode/impl/RecordServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.servicecode.impl;
2 |
3 | import android.content.Context;
4 |
5 | import com.baidu.mapapi.model.LatLng;
6 | import com.happyheng.sport_android.model.request.RecordSportMessageRequest;
7 | import com.happyheng.sport_android.model.request.SportIdRequest;
8 | import com.happyheng.sport_android.servicecode.RecordService;
9 | import com.orhanobut.logger.Logger;
10 |
11 | /**
12 | * 记录运动信息的实现类
13 | * Created by liuheng on 16/7/5.
14 | */
15 | public class RecordServiceImpl implements RecordService {
16 |
17 | private static final int SPORT_DEFAULT_ID = -1;
18 |
19 | private Context mContext;
20 | private int mSportId = SPORT_DEFAULT_ID;
21 | //分别是记录SportId的Request,和记录Sport信息的Request
22 | private SportIdRequest mSportIdRequest;
23 | private RecordSportMessageRequest mSportMessageRecordRequest;
24 |
25 | //获取SportId的回调
26 | private SportIdRequest.OnSportIdListener mGetSportIdListener = new SportIdListener();
27 |
28 | public RecordServiceImpl(Context context) {
29 | this.mContext = context;
30 | mSportIdRequest = new SportIdRequest(mGetSportIdListener);
31 | mSportMessageRecordRequest = new RecordSportMessageRequest();
32 | }
33 |
34 | @Override
35 | public void recordSport(LatLng latLng, String location) {
36 | //如果sportId尚未获取的话,那么就继续获取
37 | if (mSportId == SPORT_DEFAULT_ID) {
38 | mSportIdRequest.doRequest();
39 | }
40 | else {
41 | //如果获取成功,那么
42 | RecordSportMessageRequest.SportMessage message = new RecordSportMessageRequest.SportMessage(mSportId,latLng.longitude,latLng.latitude,location);
43 | mSportMessageRecordRequest.setMessage(message);
44 | mSportMessageRecordRequest.doRequest();
45 | }
46 | }
47 |
48 | private class SportIdListener implements SportIdRequest.OnSportIdListener{
49 |
50 | @Override
51 | public void onSuccess(int sportId) {
52 | Logger.d("获取的sportId为"+sportId);
53 | mSportId = sportId;
54 | }
55 |
56 | @Override
57 | public void onFail() {
58 |
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/AESUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import java.security.Key;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.spec.SecretKeySpec;
7 |
8 | /**
9 | * AES进行加解密的工具类
10 | * @author liuheng
11 | *
12 | */
13 | public class AESUtils {
14 |
15 | /**
16 | * AES加密的方法
17 | * @param byteskey AES的key
18 | * @param text 待加密的字符串
19 | * @return 返回转换成16进制的加密字符串,如果加密失败,返回null
20 | */
21 | public static String encrypt(byte[] byteskey,String text) {
22 | try {
23 | //转换key
24 | Key convertSecretKey = new SecretKeySpec(byteskey, "AES");
25 | //加密
26 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
27 |
28 | cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
29 | byte[] encryptResult = cipher.doFinal(text.getBytes());
30 | String encryptString = HexUtils.bytesToHexString(encryptResult);
31 |
32 | System.out.println("jdk des encrypt:" + encryptString);
33 | return encryptString;
34 |
35 | } catch (Exception e) {
36 | e.printStackTrace();
37 | return null;
38 | }
39 | }
40 |
41 | /**
42 | * AES解密的方法
43 | * @param byteskey AES的key
44 | * @param encryptString 加密并转换成16进制的字符串
45 | * @return 返回解密的字符串,如果失败,返回null
46 | */
47 | public static String decrypt(byte[] byteskey,String encryptString) {
48 | try {
49 | //转换key
50 | Key convertSecretKey = new SecretKeySpec(byteskey, "AES");
51 | // 解密
52 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
53 | cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
54 | byte[] decryptResult = cipher.doFinal(HexUtils.hexStringToBytes(encryptString));
55 | String decryptString = new String(decryptResult);
56 | System.out.println("jdk des decrypt:" + decryptString);
57 | return decryptString;
58 |
59 | } catch (Exception e) {
60 | e.printStackTrace();
61 | return null;
62 | }
63 | }
64 |
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/DensityUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.content.Context;
4 | import android.util.TypedValue;
5 |
6 | /**
7 | * 单位转换的工具类
8 | * Created by liuheng on 16/4/24.
9 | */
10 | public class DensityUtils {
11 | private DensityUtils()
12 | {
13 | /** cannot be instantiated **/
14 | throw new UnsupportedOperationException("cannot be instantiated");
15 | }
16 |
17 | /**
18 | * dp转px
19 | *
20 | * @param context
21 | * @return
22 | */
23 | public static int dp2px(Context context, float dpVal)
24 | {
25 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
26 | dpVal, context.getResources().getDisplayMetrics());
27 | }
28 |
29 | /**
30 | * sp转px
31 | *
32 | * @param context
33 | * @return
34 | */
35 | public static int sp2px(Context context, float spVal)
36 | {
37 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
38 | spVal, context.getResources().getDisplayMetrics());
39 | }
40 |
41 | /**
42 | * px转dp
43 | *
44 | * @param context
45 | * @param pxVal
46 | * @return
47 | */
48 | public static float px2dp(Context context, float pxVal)
49 | {
50 | final float scale = context.getResources().getDisplayMetrics().density;
51 | return (pxVal / scale);
52 | }
53 | /**
54 | * px转sp
55 | *
56 | * @param pxVal
57 | * @return
58 | */
59 | public static float px2sp(Context context, float pxVal)
60 | {
61 | return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/HexUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | public class HexUtils {
4 | public static String bytesToHexString(byte[] src){
5 | StringBuilder stringBuilder = new StringBuilder("");
6 | if (src == null || src.length <= 0) {
7 | return null;
8 | }
9 | for (int i = 0; i < src.length; i++) {
10 | int v = src[i] & 0xFF;
11 | String hv = Integer.toHexString(v);
12 | if (hv.length() < 2) {
13 | stringBuilder.append(0);
14 | }
15 | stringBuilder.append(hv);
16 | }
17 | return stringBuilder.toString();
18 | }
19 | /**
20 | * Convert hex string to byte[]
21 | * @param hexString the hex string
22 | * @return byte[]
23 | */
24 | public static byte[] hexStringToBytes(String hexString) {
25 | if (hexString == null || hexString.equals("")) {
26 | return null;
27 | }
28 | hexString = hexString.toUpperCase();
29 | int length = hexString.length() / 2;
30 | char[] hexChars = hexString.toCharArray();
31 | byte[] d = new byte[length];
32 | for (int i = 0; i < length; i++) {
33 | int pos = i * 2;
34 | d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
35 | }
36 | return d;
37 | }
38 | /**
39 | * Convert char to byte
40 | * @param c char
41 | * @return byte
42 | */
43 | private static byte charToByte(char c) {
44 | return (byte) "0123456789ABCDEF".indexOf(c);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/NetUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.ComponentName;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.net.ConnectivityManager;
8 | import android.net.NetworkInfo;
9 |
10 | /**
11 | * 网络判断方面的辅助类
12 | * Created by liuheng on 16/4/24.
13 | */
14 | public class NetUtils {
15 |
16 | private NetUtils()
17 | {
18 | /** cannot be instantiated **/
19 | throw new UnsupportedOperationException("cannot be instantiated");
20 | }
21 |
22 | /**
23 | * 判断网络是否连接
24 | *
25 | * @param context
26 | * @return
27 | */
28 | public static boolean isConnected(Context context)
29 | {
30 |
31 | ConnectivityManager connectivity = (ConnectivityManager) context
32 | .getSystemService(Context.CONNECTIVITY_SERVICE);
33 |
34 | if (null != connectivity)
35 | {
36 |
37 | NetworkInfo info = connectivity.getActiveNetworkInfo();
38 | if (null != info && info.isConnected())
39 | {
40 | if (info.getState() == NetworkInfo.State.CONNECTED)
41 | {
42 | return true;
43 | }
44 | }
45 | }
46 | return false;
47 | }
48 |
49 | /**
50 | * 判断是否是wifi连接
51 | */
52 | public static boolean isWifi(Context context)
53 | {
54 | ConnectivityManager cm = (ConnectivityManager) context
55 | .getSystemService(Context.CONNECTIVITY_SERVICE);
56 |
57 | if (cm == null)
58 | return false;
59 | return cm.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
60 |
61 | }
62 |
63 | /**
64 | * 打开网络设置界面
65 | */
66 | public static void openSetting(Activity activity)
67 | {
68 | Intent intent = new Intent("/");
69 | ComponentName cm = new ComponentName("com.android.settings",
70 | "com.android.settings.WirelessSettings");
71 | intent.setComponent(cm);
72 | intent.setAction("android.intent.action.VIEW");
73 | activity.startActivityForResult(intent, 0);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/SPUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | import java.lang.reflect.InvocationTargetException;
7 | import java.lang.reflect.Method;
8 | import java.util.Map;
9 |
10 | /**
11 | * SharedPreferences工具类
12 | * Created by liuheng on 16/4/24.
13 | */
14 | public class SPUtils {
15 |
16 | /**
17 | * 保存在手机里面的文件名
18 | */
19 | public static final String FILE_NAME = "share_data";
20 |
21 | /**
22 | * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
23 | *
24 | * @param context
25 | * @param key
26 | * @param object
27 | */
28 | public static void put(Context context, String key, Object object)
29 | {
30 |
31 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
32 | Context.MODE_PRIVATE);
33 | SharedPreferences.Editor editor = sp.edit();
34 |
35 | if (object instanceof String)
36 | {
37 | editor.putString(key, (String) object);
38 | } else if (object instanceof Integer)
39 | {
40 | editor.putInt(key, (Integer) object);
41 | } else if (object instanceof Boolean)
42 | {
43 | editor.putBoolean(key, (Boolean) object);
44 | } else if (object instanceof Float)
45 | {
46 | editor.putFloat(key, (Float) object);
47 | } else if (object instanceof Long)
48 | {
49 | editor.putLong(key, (Long) object);
50 | } else
51 | {
52 | editor.putString(key, object.toString());
53 | }
54 |
55 | SharedPreferencesCompat.apply(editor);
56 | }
57 | /**
58 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
59 | *
60 | * @param context
61 | * @param key
62 | * @param defaultObject
63 | * @return
64 | */
65 | public static Object get(Context context, String key, Object defaultObject)
66 | {
67 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
68 | Context.MODE_PRIVATE);
69 |
70 | if (defaultObject instanceof String)
71 | {
72 | return sp.getString(key, (String) defaultObject);
73 | } else if (defaultObject instanceof Integer)
74 | {
75 | return sp.getInt(key, (Integer) defaultObject);
76 | } else if (defaultObject instanceof Boolean)
77 | {
78 | return sp.getBoolean(key, (Boolean) defaultObject);
79 | } else if (defaultObject instanceof Float)
80 | {
81 | return sp.getFloat(key, (Float) defaultObject);
82 | } else if (defaultObject instanceof Long)
83 | {
84 | return sp.getLong(key, (Long) defaultObject);
85 | }
86 |
87 | return null;
88 | }
89 | /**
90 | * 移除某个key值已经对应的值
91 | * @param context
92 | * @param key
93 | */
94 | public static void remove(Context context, String key)
95 | {
96 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
97 | Context.MODE_PRIVATE);
98 | SharedPreferences.Editor editor = sp.edit();
99 | editor.remove(key);
100 | SharedPreferencesCompat.apply(editor);
101 | }
102 |
103 | /**
104 | * 清除所有数据
105 | * @param context
106 | */
107 | public static void clear(Context context)
108 | {
109 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
110 | Context.MODE_PRIVATE);
111 | SharedPreferences.Editor editor = sp.edit();
112 | editor.clear();
113 | SharedPreferencesCompat.apply(editor);
114 | }
115 |
116 | /**
117 | * 查询某个key是否已经存在
118 | * @param context
119 | * @param key
120 | * @return
121 | */
122 | public static boolean contains(Context context, String key)
123 | {
124 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
125 | Context.MODE_PRIVATE);
126 | return sp.contains(key);
127 | }
128 | /**
129 | * 返回所有的键值对
130 | *
131 | * @param context
132 | * @return
133 | */
134 | public static Map getAll(Context context)
135 | {
136 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
137 | Context.MODE_PRIVATE);
138 | return sp.getAll();
139 | }
140 |
141 | /**
142 | * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
143 | *
144 | * @author zhy
145 | *
146 | */
147 | private static class SharedPreferencesCompat
148 | {
149 | private static final Method sApplyMethod = findApplyMethod();
150 |
151 | /**
152 | * 反射查找apply的方法
153 | *
154 | * @return
155 | */
156 | @SuppressWarnings({ "unchecked", "rawtypes" })
157 | private static Method findApplyMethod()
158 | {
159 | try
160 | {
161 | Class clz = SharedPreferences.Editor.class;
162 | return clz.getMethod("apply");
163 | } catch (NoSuchMethodException e)
164 | {
165 | }
166 |
167 | return null;
168 | }
169 | /**
170 | * 如果找到则使用apply执行,否则使用commit
171 | *
172 | * @param editor
173 | */
174 | public static void apply(SharedPreferences.Editor editor)
175 | {
176 | try
177 | {
178 | if (sApplyMethod != null)
179 | {
180 | sApplyMethod.invoke(editor);
181 | return;
182 | }
183 | } catch (IllegalArgumentException e)
184 | {
185 | } catch (IllegalAccessException e)
186 | {
187 | } catch (InvocationTargetException e)
188 | {
189 | }
190 | editor.commit();
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/ScreenUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.graphics.Rect;
7 | import android.util.DisplayMetrics;
8 | import android.view.View;
9 | import android.view.WindowManager;
10 |
11 | /**
12 | * 屏幕宽高、状态栏高度、获取截图的辅助类
13 | * Created by liuheng on 16/4/24.
14 | */
15 | public class ScreenUtils {
16 | private ScreenUtils()
17 | {
18 | /** cannot be instantiated **/
19 | throw new UnsupportedOperationException("cannot be instantiated");
20 | }
21 |
22 | /**
23 | * 获得屏幕高度
24 | *
25 | * @param context
26 | * @return
27 | */
28 | public static int getScreenWidth(Context context)
29 | {
30 | WindowManager wm = (WindowManager) context
31 | .getSystemService(Context.WINDOW_SERVICE);
32 | DisplayMetrics outMetrics = new DisplayMetrics();
33 | wm.getDefaultDisplay().getMetrics(outMetrics);
34 | return outMetrics.widthPixels;
35 | }
36 |
37 | /**
38 | * 获得屏幕宽度
39 | *
40 | * @param context
41 | * @return
42 | */
43 | public static int getScreenHeight(Context context)
44 | {
45 | WindowManager wm = (WindowManager) context
46 | .getSystemService(Context.WINDOW_SERVICE);
47 | DisplayMetrics outMetrics = new DisplayMetrics();
48 | wm.getDefaultDisplay().getMetrics(outMetrics);
49 | return outMetrics.heightPixels;
50 | }
51 |
52 | /**
53 | * 获得状态栏的高度
54 | *
55 | * @param context
56 | * @return
57 | */
58 | public static int getStatusHeight(Context context)
59 | {
60 |
61 | int statusHeight = -1;
62 | try
63 | {
64 | Class> clazz = Class.forName("com.android.internal.R$dimen");
65 | Object object = clazz.newInstance();
66 | int height = Integer.parseInt(clazz.getField("status_bar_height")
67 | .get(object).toString());
68 | statusHeight = context.getResources().getDimensionPixelSize(height);
69 | } catch (Exception e)
70 | {
71 | e.printStackTrace();
72 | }
73 | return statusHeight;
74 | }
75 |
76 | /**
77 | * 获取当前屏幕截图,包含状态栏
78 | *
79 | * @param activity
80 | * @return
81 | */
82 | public static Bitmap snapShotWithStatusBar(Activity activity)
83 | {
84 | View view = activity.getWindow().getDecorView();
85 | view.setDrawingCacheEnabled(true);
86 | view.buildDrawingCache();
87 | Bitmap bmp = view.getDrawingCache();
88 | int width = getScreenWidth(activity);
89 | int height = getScreenHeight(activity);
90 | Bitmap bp = null;
91 | bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
92 | view.destroyDrawingCache();
93 | return bp;
94 |
95 | }
96 |
97 | /**
98 | * 获取当前屏幕截图,不包含状态栏
99 | *
100 | * @param activity
101 | * @return
102 | */
103 | public static Bitmap snapShotWithoutStatusBar(Activity activity)
104 | {
105 | View view = activity.getWindow().getDecorView();
106 | view.setDrawingCacheEnabled(true);
107 | view.buildDrawingCache();
108 | Bitmap bmp = view.getDrawingCache();
109 | Rect frame = new Rect();
110 | activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
111 | int statusBarHeight = frame.top;
112 |
113 | int width = getScreenWidth(activity);
114 | int height = getScreenHeight(activity);
115 | Bitmap bp = null;
116 | bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
117 | - statusBarHeight);
118 | view.destroyDrawingCache();
119 | return bp;
120 |
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/SimpleStartActivityUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 |
6 | /**
7 | * 简单的跳转Activity的工具类
8 | * Created by liuheng on 16/6/7.
9 | */
10 | public class SimpleStartActivityUtils {
11 | public static void startActivity(Context context, Class> cls) {
12 | Intent intent = new Intent(context, cls);
13 | context.startActivity(intent);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/ThreadUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | /**
7 | * 线程的工具类
8 | * Created by liuheng on 16/6/9.
9 | */
10 | public class ThreadUtils {
11 |
12 | /**
13 | * 在子线程中执行
14 | * @param runnable
15 | */
16 | public static void runOnNewThread(Runnable runnable){
17 | new Thread(runnable).start();
18 | }
19 |
20 | /**
21 | * 在主线程中执行
22 | * @param runnable
23 | */
24 | public static void runOnMainThread(Runnable runnable){
25 | Handler handler = new Handler(Looper.getMainLooper());
26 | handler.post(runnable);
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/utils/ToastUtils.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.utils;
2 |
3 | import android.content.Context;
4 | import android.widget.Toast;
5 |
6 | /**
7 | * 吐司的辅助类
8 | * Created by liuheng on 16/6/8.
9 | */
10 | public class ToastUtils {
11 |
12 | public static void showToast(Context context, String content) {
13 | showToast(context, content, false);
14 | }
15 |
16 | public static void showToast(Context context, String content, boolean isLongToast) {
17 | int length;
18 | if (isLongToast) {
19 | length = Toast.LENGTH_LONG;
20 | } else {
21 | length = Toast.LENGTH_SHORT;
22 | }
23 |
24 | Toast.makeText(context, content, length).show();
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/view/MainBottomView.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.ImageView;
8 | import android.widget.LinearLayout;
9 |
10 | import com.happyheng.sport_android.R;
11 |
12 | /**
13 | * 主页顶部的View
14 | * Created by liuheng on 16/7/12.
15 | */
16 | public class MainBottomView extends LinearLayout {
17 |
18 | //默认选择的位置
19 | private static final int DEFAULT_POSITION = 0;
20 | private static final int TAB_NUM = 3;
21 |
22 | private final int[] UNSELECTED_IMAGE_BG = new int[]{R.mipmap.tab_information_unselected,R.mipmap.tab_sport_unselected,R.mipmap.tab_me_unselected};
23 | private final int[] SELECTED_IMAGE_BG = new int[]{R.mipmap.tab_information_selected,R.mipmap.tab_sport_selected,R.mipmap.tab_me_selected};
24 |
25 | private View mInformationTab, mSportTab, mMineTab;
26 | private ImageView mInformationIv,mSportIv,mMineIv;
27 | private ImageView[] mImages = new ImageView[TAB_NUM];
28 |
29 | private View.OnClickListener mClickListener = new ClickListener();
30 |
31 | private int mSelectIndex = DEFAULT_POSITION;
32 |
33 | public MainBottomView(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 |
36 | setOrientation(HORIZONTAL);
37 | LayoutInflater.from(context).inflate(R.layout.view_main_bottom, this, true);
38 |
39 | mInformationTab = findViewById(R.id.tab_information);
40 | mSportTab = findViewById(R.id.tab_sport);
41 | mMineTab = findViewById(R.id.tab_mine);
42 |
43 |
44 | mInformationIv = (ImageView) findViewById(R.id.information_iv);
45 | mSportIv = (ImageView) findViewById(R.id.sport_iv);
46 | mMineIv = (ImageView) findViewById(R.id.mine_iv);
47 | mImages[0] = mInformationIv;
48 | mImages[1] = mSportIv;
49 | mImages[2] = mMineIv;
50 |
51 | setImageState(mSelectIndex,true);
52 |
53 | mInformationTab.setOnClickListener(mClickListener);
54 | mSportTab.setOnClickListener(mClickListener);
55 | mMineTab.setOnClickListener(mClickListener);
56 | }
57 |
58 | private class ClickListener implements View.OnClickListener {
59 |
60 | @Override
61 | public void onClick(View v) {
62 |
63 | if (mBottomClickListener != null) {
64 |
65 | int newSelect;
66 | switch (v.getId()) {
67 | case R.id.tab_information:
68 | newSelect = 0;
69 | break;
70 |
71 | case R.id.tab_sport:
72 | newSelect = 1;
73 | break;
74 |
75 | default:
76 | newSelect = 2;
77 | break;
78 | }
79 |
80 | if (mSelectIndex != newSelect){
81 | setImageState(mSelectIndex,false);
82 | setImageState(newSelect,true);
83 |
84 | mBottomClickListener.onClick(mSelectIndex, newSelect);
85 | mSelectIndex = newSelect;
86 | }
87 |
88 | }
89 |
90 | }
91 | }
92 |
93 | private void setImageState(int position,boolean isSelected){
94 | if (isSelected){
95 | mImages[position].setBackgroundDrawable(getResources().getDrawable(SELECTED_IMAGE_BG[position]));
96 | } else {
97 | mImages[position].setBackgroundDrawable(getResources().getDrawable(UNSELECTED_IMAGE_BG[position]));
98 | }
99 | }
100 |
101 |
102 | public interface OnBottomChooseListener {
103 | void onClick(int oldPositon,int position);
104 | }
105 |
106 | private OnBottomChooseListener mBottomClickListener;
107 |
108 | public void setBottomCLickListener(OnBottomChooseListener bottomCLickListener) {
109 | this.mBottomClickListener = bottomCLickListener;
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/view/NewsItemView.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.view;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.widget.ImageView;
7 | import android.widget.LinearLayout;
8 | import android.widget.TextView;
9 |
10 | import com.bumptech.glide.Glide;
11 | import com.happyheng.sport_android.R;
12 | import com.orhanobut.logger.Logger;
13 |
14 | /**
15 | *
16 | * Created by liuheng on 16/7/24.
17 | */
18 | public class NewsItemView extends LinearLayout {
19 |
20 | //顶部的缩略图
21 | private ImageView mThumbnailIv;
22 | private TextView mTitleTv, mContentTv;
23 |
24 | public NewsItemView(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | LayoutInflater.from(context).inflate(R.layout.item_news, this, true);
27 |
28 | mThumbnailIv = (ImageView) findViewById(R.id.item_thumbnail_iv);
29 | mTitleTv = (TextView) findViewById(R.id.title_tv);
30 | mContentTv = (TextView) findViewById(R.id.content_tv);
31 | }
32 |
33 | public void setThumbnailSource(String url) {
34 | Glide.with(getContext()).load(url).into(mThumbnailIv);
35 | }
36 |
37 | public void setTitleString(String title) {
38 | mTitleTv.setText(title);
39 | }
40 |
41 | public void setContentString(String content) {
42 | mContentTv.setText(content);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/java/com/happyheng/sport_android/view/TabSportBackView.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Path;
7 | import android.util.AttributeSet;
8 | import android.view.View;
9 |
10 | import com.happyheng.sport_android.R;
11 |
12 | /**
13 | * 运动界面的背景View
14 | * Created by liuheng on 16/7/16.
15 | */
16 | public class TabSportBackView extends View {
17 |
18 | private Paint mPaint;
19 | private int mBackHeight,mBackBottomHeight;
20 | private Path mBottomPath;
21 |
22 | public TabSportBackView(Context context, AttributeSet attrs) {
23 | super(context, attrs);
24 |
25 | int backColor = context.getResources().getColor(R.color.sport_bg);
26 | mPaint = new Paint();
27 | mPaint.setColor(backColor);
28 | mPaint.setStyle(Paint.Style.FILL);
29 |
30 | mBottomPath =new Path();
31 |
32 | mBackHeight = getResources().getDimensionPixelSize(R.dimen.tab_sport_top_height);
33 | mBackBottomHeight = getResources().getDimensionPixelSize(R.dimen.tab_sport_oval_half_height);
34 | }
35 |
36 | @Override
37 | protected void onDraw(Canvas canvas) {
38 | super.onDraw(canvas);
39 |
40 | canvas.drawRect(0, 0, getMeasuredWidth(), mBackHeight, mPaint);
41 |
42 | mBottomPath.moveTo(0, mBackHeight);
43 | mBottomPath.lineTo(getMeasuredWidth()/2, mBackHeight + mBackBottomHeight);
44 | mBottomPath.lineTo(getMeasuredWidth(), mBackHeight);
45 | mBottomPath.close();
46 | canvas.drawPath(mBottomPath,mPaint);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_oval.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_information.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_sport.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_sport_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_sport_button_press.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_tab_sport_normal.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_login.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
14 |
15 |
20 |
21 |
28 |
29 |
37 |
38 |
39 |
40 |
41 |
42 |
49 |
50 |
57 |
58 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
13 |
14 |
15 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_map.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
16 |
17 |
25 |
26 |
35 |
36 |
45 |
46 |
54 |
55 |
56 |
57 |
58 |
63 |
64 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sport_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_sport_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_base_recycler.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_information.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sport.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
19 |
20 |
26 |
27 |
32 |
33 |
37 |
38 |
46 |
47 |
48 |
55 |
56 |
63 |
64 |
65 |
66 |
67 |
71 |
72 |
76 |
77 |
85 |
86 |
87 |
94 |
95 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
115 |
116 |
121 |
122 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_load_more.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_news.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
23 |
24 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_sport_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_main_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
17 |
18 |
22 |
23 |
24 |
27 |
28 |
34 |
35 |
39 |
40 |
41 |
42 |
45 |
46 |
52 |
53 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_information_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_information_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_information_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_information_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_me_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_me_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_me_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_me_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_sport_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_sport_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/tab_sport_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xhdpi/tab_sport_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/tab_me_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxhdpi/tab_me_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/tab_me_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxhdpi/tab_me_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/tab_sport_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxhdpi/tab_sport_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/tab_sport_unselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxhdpi/tab_sport_unselected.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/user_icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxhdpi/user_icon.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/icon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/app/src/main/res/mipmap-xxxhdpi/icon.jpg
--------------------------------------------------------------------------------
/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 | #fff
8 | #f00
9 |
10 | #0099ff
11 |
12 | #ff6eb958
13 | #6fba58
14 | #28b046
15 |
16 | #f8f8fa
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
7 | 300dp
8 | 50dp
9 |
10 |
11 | 50dp
12 | 24dp
13 |
14 |
15 | 350dp
16 | 70dp
17 | 140dp
18 |
19 | 130dp
20 | 12dp
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.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 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
15 |
16 |
17 |
20 |
21 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/test/java/com/happyheng/sport_android/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.happyheng.sport_android;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/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:1.5.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 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
25 |
--------------------------------------------------------------------------------
/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 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/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.10-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 |
--------------------------------------------------------------------------------
/screenshot/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/screenshot/1.png
--------------------------------------------------------------------------------
/screenshot/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/screenshot/2.png
--------------------------------------------------------------------------------
/screenshot/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/screenshot/3.png
--------------------------------------------------------------------------------
/screenshot/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/screenshot/4.png
--------------------------------------------------------------------------------
/screenshot/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/happyheng/Sport_Android/599b7e75fc8b00085e19285b8765c596e45daa1c/screenshot/5.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------