├── .gitignore ├── .idea ├── .name ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ ├── app-release.apk │ └── output.json └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── pkuhelper │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── pace.json │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── pkuhelper │ │ │ ├── CustomVideoView.java │ │ │ ├── DoActivity.java │ │ │ ├── LoginActivity.java │ │ │ ├── MainActivity.java │ │ │ └── Record.java │ └── res │ │ ├── drawable │ │ ├── all.png │ │ ├── bk.jpg │ │ ├── bussiness.png │ │ ├── down.png │ │ ├── flag.png │ │ ├── man.jpeg │ │ ├── map.png │ │ ├── normal_btn.xml │ │ ├── right.png │ │ └── weather.png │ │ ├── layout │ │ ├── activity_do.xml │ │ ├── activity_login.xml │ │ ├── activity_main.xml │ │ └── nav_header.xml │ │ ├── menu │ │ ├── nav_menu.xml │ │ └── toolbar.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.jpg │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.jpg │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.jpg │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.jpg │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.jpg │ │ └── ic_launcher_round.png │ │ ├── raw │ │ └── welcome_start.mp4 │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── pkuhelper │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── imgs ├── 1.png ├── 2.png └── 3.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | 36k -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PKURUNNER-Helper 2 | PKURUNNER助手安卓版客户端 3 | 4 | ### 改写自学长的项目https://github.com/fieryd/PKURunningHelper 5 | ### 将Python程序改写成安卓移动应用 6 | 7 | # screenshot 8 | ![](https://github.com/LoseNine/PKURunnerHelper/blob/master/imgs/1.png) 9 | ![](https://github.com/LoseNine/PKURunnerHelper/blob/master/imgs/2.png) 10 | ![](https://github.com/LoseNine/PKURunnerHelper/blob/master/imgs/3.png) 11 | 12 | ### 注意:由于我有些懒惰,PKURUNNER又不停迭代版本,每次都要写,不想改这个项目了 13 | ### 我会把Python版本的关键参数放一下 14 | ### 2021-03-25修改了abstract参数 15 | ### 使用Python版本,只需要加上参数 16 | 'abstract':str(hashlib.sha256(f'{self.studentID}_{record.date}_781f5106781f5106'.encode()).hexdigest()[:32]) 17 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 29 5 | buildToolsVersion "29.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.example.pkuhelper" 9 | minSdkVersion 21 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: 'libs', include: ['*.jar']) 28 | 29 | implementation 'androidx.appcompat:appcompat:1.1.0' 30 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 31 | implementation 'com.google.android.material:material:1.1.0' 32 | implementation 'androidx.annotation:annotation:1.1.0' 33 | implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' 34 | testImplementation 'junit:junit:4.12' 35 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 36 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 37 | 38 | //noinspection GradleCompatible 39 | implementation 'com.android.support:appcompat-v7:21.0.3' 40 | implementation 'org.jsoup:jsoup:1.13.1' 41 | implementation 'com.google.code.gson:gson:2.8.1' 42 | 43 | //noinspection GradleCompatible 44 | implementation 'com.android.support:design:24.2.1' 45 | implementation 'de.hdodenhof:circleimageview:2.1.0' 46 | } 47 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/release/app-release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/release/app-release.apk -------------------------------------------------------------------------------- /app/release/output.json: -------------------------------------------------------------------------------- 1 | [{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}] -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/pkuhelper/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("com.example.pkuhelper", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/assets/pace.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | [116.31275393507501, 39.9878930992251, 0], 4 | [116.31275787121162, 39.987877034107946, 0], 5 | [116.31275499378225, 39.98786189587606, 0], 6 | [116.31275912029979, 39.98784701244487, 0], 7 | [116.3127610714635, 39.987824664926045, 0], 8 | [116.3127603976012, 39.987804762941835, 0], 9 | [116.31276184834093, 39.987787144745845, 0], 10 | [116.31276368067158, 39.98777603747929, 0], 11 | [116.31276686630442, 39.98776934274656, 0], 12 | [116.3127653331318, 39.987768880061154, 0], 13 | [116.31276647408548, 39.98775799160118, 0], 14 | [116.31276315602434, 39.98774493269005, 0], 15 | [116.31276813425668, 39.98772991073608, 0], 16 | [116.31277506653812, 39.987715512207046, 0], 17 | [116.31278109724269, 39.98770314219317, 0], 18 | [116.31278347039677, 39.98768982577828, 0], 19 | [116.31278598351472, 39.987673949502565, 0], 20 | [116.31278738679648, 39.98765858045474, 0], 21 | [116.31278659949348, 39.987642912365324, 0], 22 | [116.31279119732803, 39.987630849873696, 0], 23 | [116.31279453423541, 39.98761561679905, 0], 24 | [116.3127915662432, 39.98759998099655, 0], 25 | [116.31279363804076, 39.98758071381584, 0], 26 | [116.31278450693725, 39.98756041709926, 0], 27 | [116.31277609673334, 39.987535591453614, 0], 28 | [116.31277075379246, 39.98751897148007, 0], 29 | [116.31276895784318, 39.98750061760707, 0], 30 | [116.3127759598046, 39.98748250905066, 0], 31 | [116.31278125845758, 39.987465617581016, 0], 32 | [116.31277870150852, 39.987451632561886, 0], 33 | [116.31278600502412, 39.9874410248372, 0], 34 | [116.31279282719777, 39.9874275061571, 0], 35 | [116.31279345621506, 39.98740945651578, 0], 36 | [116.31279303302054, 39.98739082501979, 0], 37 | [116.31279515501922, 39.987372347959145, 0], 38 | [116.31280638587995, 39.98735661686243, 0], 39 | [116.31280971109634, 39.98734429214715, 0], 40 | [116.31281098291439, 39.98733816411084, 0], 41 | [116.3128146892996, 39.987328980187264, 0], 42 | [116.31281415695291, 39.9873188888494, 0], 43 | [116.3128152274772, 39.987305700175064, 0], 44 | [116.31281480487131, 39.987291758871315, 0], 45 | [116.31280625603877, 39.98728017352066, 0], 46 | [116.31279914028434, 39.98726989071813, 0], 47 | [116.31279763550475, 39.98725615753981, 0], 48 | [116.31279955757326, 39.9872414802865, 0], 49 | [116.31280071768423, 39.987223541574366, 0], 50 | [116.31279886191786, 39.98720762769643, 0], 51 | [116.31279925074763, 39.98719197773539, 0], 52 | [116.31280023055213, 39.98717451872911, 0], 53 | [116.31280442649728, 39.987153885190565, 0], 54 | [116.3128141336467, 39.98713324124375, 0], 55 | [116.31282205747979, 39.98711505429452, 0], 56 | [116.31283002139205, 39.987096837414875, 0], 57 | [116.31283902772915, 39.98708104244965, 0], 58 | [116.31285401656504, 39.98706786800837, 0], 59 | [116.31286219120857, 39.98705202159636, 0], 60 | [116.31287489494757, 39.987035213033245, 0], 61 | [116.31289567585517, 39.98702421877757, 0], 62 | [116.31291656713483, 39.98701432476587, 0], 63 | [116.31292721692783, 39.98699927270678, 0], 64 | [116.31294133388099, 39.98698500672295, 0], 65 | [116.31295544084826, 39.98697098073467, 0], 66 | [116.31296987843194, 39.986956465305894, 0], 67 | [116.31298756293319, 39.986944335637624, 0], 68 | [116.31300356399603, 39.986932083034255, 0], 69 | [116.3130171101241, 39.986920326174435, 0], 70 | [116.3130295938678, 39.98690678739229, 0], 71 | [116.31304433276085, 39.98689763272436, 0], 72 | [116.31306137633636, 39.98688831207335, 0], 73 | [116.31307988308626, 39.98688046403966, 0], 74 | [116.31310514413977, 39.986876767966905, 0], 75 | [116.3131252945291, 39.98687106290205, 0], 76 | [116.31314989343322, 39.98686079542388, 0], 77 | [116.31316921262172, 39.986858889076515, 0], 78 | [116.31318824087982, 39.986854232114965, 0], 79 | [116.31320472382409, 39.98684858067278, 0], 80 | [116.31322391191219, 39.98683984383498, 0], 81 | [116.31324015508869, 39.9868398522135, 0], 82 | [116.31325553738787, 39.98685084937632, 0], 83 | [116.31326993687946, 39.98685242456377, 0], 84 | [116.31328256329186, 39.98685730683067, 0], 85 | [116.3132958706661, 39.98686130149626, 0], 86 | [116.31331211337971, 39.98686584838728, 0], 87 | [116.3133284972699, 39.98686700716253, 0], 88 | [116.31335003190297, 39.98687179501637, 0], 89 | [116.31337257782425, 39.98687527438965, 0], 90 | [116.31339274854693, 39.986878959501415, 0], 91 | [116.31341751924421, 39.98688105284868, 0], 92 | [116.31344985622464, 39.98688637970345, 0], 93 | [116.31348298485659, 39.98689076796314, 0], 94 | [116.31350960062774, 39.98691380498138, 0], 95 | [116.3135304138734, 39.98691564163416, 0], 96 | [116.31355505524276, 39.98692362508823, 0], 97 | [116.3135493642188, 39.98693872532481, 0], 98 | [116.31355701179557, 39.986948919342616, 0], 99 | [116.3135786881616, 39.98696236795533, 0], 100 | [116.31359993312934, 39.98697663564893, 0], 101 | [116.31361304152655, 39.986987749119975, 0], 102 | [116.3136294768796, 39.98698888846838, 0], 103 | [116.313638597008, 39.987000234921024, 0], 104 | [116.31364969172321, 39.987015845011134, 0], 105 | [116.31365869216137, 39.98703159143593, 0], 106 | [116.31366501771252, 39.9870521233656, 0], 107 | [116.31367592201448, 39.987067503116944, 0], 108 | [116.3136884495793, 39.9870823156945, 0], 109 | [116.31369944341891, 39.987092495395094, 0], 110 | [116.31371249107038, 39.98709942856878, 0], 111 | [116.31372077947601, 39.98711052356355, 0], 112 | [116.31372379720352, 39.98712274935672, 0], 113 | [116.31372741594224, 39.98713319613221, 0], 114 | [116.31373062021486, 39.98714543751821, 0], 115 | [116.31373530742849, 39.98715684147322, 0], 116 | [116.31374072828797, 39.98716891849932, 0], 117 | [116.31373821310485, 39.98717088036862, 0], 118 | [116.31374020694073, 39.98718520269653, 0], 119 | [116.31374276796769, 39.98719059255305, 0], 120 | [116.31374152806258, 39.98720167123558, 0], 121 | [116.31373815341198, 39.98721986605382, 0], 122 | [116.31373759866116, 39.987240210643776, 0], 123 | [116.31373674657915, 39.987253947953, 0], 124 | [116.31373757790695, 39.987267308201424, 0], 125 | [116.31373650552925, 39.98728229517504, 0], 126 | [116.3137352551845, 39.98730003370358, 0], 127 | [116.31373438129749, 39.9873161093151, 0], 128 | [116.31373233489251, 39.987331302833134, 0], 129 | [116.31373148473442, 39.98734397185758, 0], 130 | [116.31372684686407, 39.987355032943945, 0], 131 | [116.31372867614293, 39.98736846143683, 0], 132 | [116.31372581988955, 39.98738174521113, 0], 133 | [116.31372234853244, 39.98739714448307, 0], 134 | [116.31371981880004, 39.98741007530724, 0], 135 | [116.31371471970428, 39.98742102680679, 0], 136 | [116.31370924039368, 39.98743648782353, 0], 137 | [116.31370681727756, 39.987451314176745, 0], 138 | [116.31370542620633, 39.987465552316735, 0], 139 | [116.31370323360247, 39.9874806890872, 0], 140 | [116.31369507848854, 39.98749365530914, 0], 141 | [116.31368898753003, 39.98750596512621, 0], 142 | [116.31368791697307, 39.98751905378201, 0], 143 | [116.31368645572826, 39.98753305178962, 0], 144 | [116.31368613725134, 39.98755042193937, 0], 145 | [116.31368609926238, 39.987567092552624, 0], 146 | [116.31368710379168, 39.9875867851179, 0], 147 | [116.31369126460145, 39.987604903155706, 0], 148 | [116.31369010384425, 39.98761787164848, 0], 149 | [116.31368992534006, 39.987632731941524, 0], 150 | [116.31368799312476, 39.98764669912184, 0], 151 | [116.31368567032719, 39.987662415688476, 0], 152 | [116.31368263613605, 39.98767866102895, 0], 153 | [116.313677617401, 39.98769114273511, 0], 154 | [116.31367618616046, 39.98770468077708, 0], 155 | [116.31367515588067, 39.98771931956727, 0], 156 | [116.31367766299722, 39.98773505460674, 0], 157 | [116.31367802636711, 39.9877559960986, 0], 158 | [116.31367888094942, 39.98777856851866, 0], 159 | [116.31368048674015, 39.98779848214793, 0], 160 | [116.3136834048798, 39.987815647967096, 0], 161 | [116.31368815649844, 39.987830546910104, 0], 162 | [116.31368598396666, 39.987845923726766, 0], 163 | [116.31368002205734, 39.987848523375185, 0], 164 | [116.31367324856718, 39.98785179162798, 0], 165 | [116.31365798603576, 39.987842094464504, 0], 166 | [116.31365153312511, 39.98784471325526, 0], 167 | [116.31365591401112, 39.98785986155602, 0], 168 | [116.31365643714223, 39.98787628314371, 0], 169 | [116.31365450523597, 39.98789270042596, 0], 170 | [116.31365165125997, 39.9879076960333, 0], 171 | [116.31365160328818, 39.98792466664197, 0], 172 | [116.31365325897104, 39.987942910290194, 0], 173 | [116.3136526900733, 39.98796102003193, 0], 174 | [116.31365035745407, 39.98797830664726, 0], 175 | [116.31364815502813, 39.98799500346691, 0], 176 | [116.31364897810535, 39.98800608536272, 0], 177 | [116.31364923042888, 39.988020496393645, 0], 178 | [116.31364612602336, 39.98803616158964, 0], 179 | [116.3136409576431, 39.98805389325113, 0], 180 | [116.31363831432064, 39.98807064930059, 0], 181 | [116.31363267481314, 39.988087090084, 0], 182 | [116.31362855827868, 39.98810232348875, 0], 183 | [116.3136214053586, 39.98811629151884, 0], 184 | [116.31361160678674, 39.98812844483778, 0], 185 | [116.31360134745879, 39.98814208741141, 0], 186 | [116.31358614773005, 39.988153541238596, 0], 187 | [116.31357816275093, 39.98816463769798, 0], 188 | [116.31356748225994, 39.98817582943883, 0], 189 | [116.31355644110234, 39.98818758057239, 0], 190 | [116.3135489067549, 39.98819630772819, 0], 191 | [116.31354005955902, 39.98820376253294, 0], 192 | [116.31353048084452, 39.98821104605047, 0], 193 | [116.31352172401525, 39.988219921074055, 0], 194 | [116.31351202533067, 39.98822937447286, 0], 195 | [116.31349989150551, 39.98823759355809, 0], 196 | [116.31348547278054, 39.98824402857174, 0], 197 | [116.31346962125996, 39.9882515311237, 0], 198 | [116.31345804838773, 39.98825810113155, 0], 199 | [116.31344029260967, 39.98826266023689, 0], 200 | [116.31342699643032, 39.98827092730334, 0], 201 | [116.31341092391861, 39.98827396930074, 0], 202 | [116.31338511120342, 39.988274764169375, 0], 203 | [116.31336765599181, 39.98827871379571, 0], 204 | [116.31335435956849, 39.98828487079056, 0], 205 | [116.31333840740844, 39.98828855304278, 0], 206 | [116.3133229363579, 39.98829319617946, 0], 207 | [116.31330495990132, 39.98829552484524, 0], 208 | [116.31328748436782, 39.98829699435656, 0], 209 | [116.31327277475015, 39.9883005187906, 0], 210 | [116.31325632161486, 39.98830436019424, 0], 211 | [116.31323765373307, 39.98830637765801, 0], 212 | [116.31321996746652, 39.988305226712534, 0], 213 | [116.31319968590219, 39.9883040312372, 0], 214 | [116.31317955453318, 39.9883018759914, 0], 215 | [116.31316090602431, 39.98829832328385, 0], 216 | [116.31314105528394, 39.98829647855288, 0], 217 | [116.31311710611787, 39.98829404665112, 0], 218 | [116.31309489028303, 39.98828988771233, 0], 219 | [116.31307493909844, 39.98829090273932, 0], 220 | [116.31305221208916, 39.98828852287381, 0], 221 | [116.31303500595729, 39.98828206251863, 0], 222 | [116.31301779976667, 39.98827308214679, 0], 223 | [116.31297235388618, 39.98826678184424, 0], 224 | [116.31295418575655, 39.98826776981186, 0], 225 | [116.31293941471178, 39.988260043756456, 0], 226 | [116.31292610637293, 39.98826011016271, 0], 227 | [116.3129108038658, 39.988259273061, 0], 228 | [116.31289662372842, 39.98823907794416, 0], 229 | [116.31288490853277, 39.98822825709786, 0], 230 | [116.31287189052634, 39.988216133931834, 0], 231 | [116.31285834119086, 39.98820199976124, 0], 232 | [116.31284972191958, 39.98818812418738, 0], 233 | [116.312843998484, 39.98817380363797, 0], 234 | [116.31283542915291, 39.98816861809955, 0], 235 | [116.3128270700995, 39.98814222287895, 0], 236 | [116.31281712761468, 39.98812412483393, 0], 237 | [116.31281162454614, 39.98811912464338, 0], 238 | [116.31280051035351, 39.988103742076, 0], 239 | [116.31279681098835, 39.98809902503668, 0], 240 | [116.31279030574696, 39.98808293305849, 0], 241 | [116.31279174633163, 39.988076847506736, 0], 242 | [116.31278534105758, 39.98806885562653, 0], 243 | [116.31276377957242, 39.988041186968256, 0], 244 | [116.31276666912607, 39.98803448913473, 0], 245 | [116.31276753905879, 39.988029840050235, 0], 246 | [116.31276116690342, 39.988017377593526, 0], 247 | [116.31275740579398, 39.98801334613636, 0], 248 | [116.31274740399665, 39.987997724195915, 0], 249 | [116.31275057864153, 39.98797328913101, 0], 250 | [116.31275122229727, 39.98795957317161, 0], 251 | [116.31275222229727, 39.98794357317161, 0], 252 | [116.3127545696661, 39.98792916161092, 0] 253 | ] 254 | } 255 | 256 | 257 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/pkuhelper/CustomVideoView.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.VideoView; 6 | 7 | public class CustomVideoView extends VideoView { 8 | public CustomVideoView(Context context){ 9 | super(context); 10 | } 11 | 12 | public CustomVideoView(Context context, AttributeSet attrs){ 13 | super(context,attrs); 14 | } 15 | 16 | public CustomVideoView(Context context,AttributeSet attrs,int defStyleAttr){ 17 | super(context,attrs,defStyleAttr); 18 | } 19 | protected void onMeasure(int widths,int heights){ 20 | int width=getDefaultSize(0,widths); 21 | int height=getDefaultSize(0,heights); 22 | setMeasuredDimension(width,height); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/pkuhelper/DoActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.appcompat.app.ActionBar; 5 | import androidx.appcompat.app.AlertDialog; 6 | import androidx.appcompat.app.AppCompatActivity; 7 | import androidx.appcompat.widget.Toolbar; 8 | import androidx.core.view.GravityCompat; 9 | import androidx.drawerlayout.widget.DrawerLayout; 10 | 11 | import android.content.DialogInterface; 12 | import android.content.Intent; 13 | import android.os.Bundle; 14 | import android.util.Log; 15 | import android.view.Menu; 16 | import android.view.MenuItem; 17 | import android.view.View; 18 | import android.widget.Button; 19 | import android.widget.SeekBar; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.google.android.material.navigation.NavigationView; 24 | 25 | import org.jsoup.Connection; 26 | import org.jsoup.Jsoup; 27 | import org.jsoup.nodes.Document; 28 | 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.io.InputStreamReader; 32 | 33 | 34 | public class DoActivity extends AppCompatActivity { 35 | private DrawerLayout mdrawerLayout; 36 | private TextView seekText,paceText,frequencyText,marque; 37 | private SeekBar seekBar,seekBarPace,seekBarFrequency; 38 | private Button doit; 39 | 40 | 41 | private double Distence=5; 42 | private double Pace=5; 43 | private double Stride_frequncy=160; 44 | 45 | public String username; 46 | public String token; 47 | 48 | public String getUsername(){ 49 | return this.username; 50 | } 51 | public String getToken(){ 52 | return this.token; 53 | } 54 | 55 | @Override 56 | protected void onCreate(Bundle savedInstanceState) { 57 | super.onCreate(savedInstanceState); 58 | setContentView(R.layout.activity_do); 59 | Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar); 60 | setSupportActionBar(toolbar); 61 | mdrawerLayout=(DrawerLayout)findViewById(R.id.drawer_layout); 62 | NavigationView navView=(NavigationView)findViewById(R.id.nav_view) ; 63 | ActionBar actionBar=getSupportActionBar(); 64 | actionBar.setDisplayHomeAsUpEnabled(true); 65 | actionBar.setHomeAsUpIndicator(R.drawable.all); 66 | 67 | 68 | navView.setCheckedItem(R.id.nav_home); 69 | navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { 70 | @Override 71 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 72 | 73 | switch (item.getItemId()) 74 | { 75 | case R.id.nav_home: 76 | Toast.makeText(getApplicationContext(),"暂时没有开发页面跳转",Toast.LENGTH_SHORT) 77 | .show(); 78 | break; 79 | case R.id.nav_weather: 80 | WeatherThread weatherThread=new WeatherThread(); 81 | weatherThread.start(); 82 | try { 83 | weatherThread.join(); 84 | } catch (InterruptedException e) { 85 | e.printStackTrace(); 86 | } 87 | String log=weatherThread.weather(); 88 | Toast.makeText(getApplicationContext(),log,Toast.LENGTH_SHORT) 89 | .show(); 90 | break; 91 | case R.id.nav_flag: 92 | UserThread userThread = new UserThread(getUsername(),getToken()); 93 | userThread.start(); 94 | try { 95 | userThread.join(); 96 | } catch (InterruptedException e) { 97 | e.printStackTrace(); 98 | } 99 | String log2=userThread.getRes(); 100 | Toast.makeText(getApplicationContext(),log2,Toast.LENGTH_SHORT) 101 | .show(); 102 | break; 103 | default: 104 | break; 105 | } 106 | 107 | mdrawerLayout.closeDrawers(); 108 | return true; 109 | } 110 | }); 111 | 112 | Intent intent = getIntent(); 113 | Bundle bundle = intent.getExtras(); 114 | String str1 = bundle.getString("username"); 115 | String str2 = bundle.getString("token"); 116 | this.username=str1; 117 | this.token=str2; 118 | 119 | marque=(TextView)findViewById(R.id.marque); 120 | marque.setSelected(true); 121 | 122 | Toast.makeText(DoActivity.this, "欢迎使用!", Toast.LENGTH_SHORT).show(); 123 | 124 | seekText = (TextView) findViewById(R.id.seekText); 125 | seekBar = (SeekBar) findViewById(R.id.seekBar); 126 | /* 设置SeekBar 监听setOnSeekBarChangeListener */ 127 | seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 128 | /*拖动条停止拖动时调用 */ 129 | @Override 130 | public void onStopTrackingTouch(SeekBar seekBar) { 131 | Log.i("SeekBarActivity", "拖动停止"); 132 | Distence=seekBar.getProgress(); 133 | } 134 | /*拖动条开始拖动时调用*/ 135 | @Override 136 | public void onStartTrackingTouch(SeekBar seekBar) { 137 | Log.i("SeekBarActivity", "开始拖动"); 138 | } 139 | /* 拖动条进度改变时调用*/ 140 | @Override 141 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 142 | seekText.setText("设置跑步距离: " + progress + " km"); 143 | } 144 | }); 145 | 146 | paceText = (TextView) findViewById(R.id.paceText); 147 | seekBarPace = (SeekBar) findViewById(R.id.seekBarPace); 148 | /* 设置SeekBar 监听setOnSeekBarChangeListener */ 149 | seekBarPace.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 150 | /*拖动条停止拖动时调用 */ 151 | @Override 152 | public void onStopTrackingTouch(SeekBar seekBar) { 153 | Log.i("SeekBarActivity", "拖动停止"); 154 | Pace=seekBarPace.getProgress(); 155 | } 156 | /*拖动条开始拖动时调用*/ 157 | @Override 158 | public void onStartTrackingTouch(SeekBar seekBar) { 159 | Log.i("SeekBarActivity", "开始拖动"); 160 | } 161 | /* 拖动条进度改变时调用*/ 162 | @Override 163 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 164 | paceText.setText("设置跑步速度: " + progress + " min/km"); 165 | } 166 | }); 167 | 168 | frequencyText = (TextView) findViewById(R.id.frequencyText); 169 | seekBarFrequency = (SeekBar) findViewById(R.id.seekBarFrequency); 170 | /* 设置SeekBar 监听setOnSeekBarChangeListener */ 171 | seekBarFrequency.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 172 | /*拖动条停止拖动时调用 */ 173 | @Override 174 | public void onStopTrackingTouch(SeekBar seekBar) { 175 | Log.i("SeekBarActivity", "拖动停止"); 176 | Stride_frequncy=seekBarFrequency.getProgress(); 177 | } 178 | /*拖动条开始拖动时调用*/ 179 | @Override 180 | public void onStartTrackingTouch(SeekBar seekBar) { 181 | Log.i("SeekBarActivity", "开始拖动"); 182 | } 183 | /* 拖动条进度改变时调用*/ 184 | @Override 185 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 186 | frequencyText.setText("迈步频率 " + progress + " step/min"); 187 | } 188 | }); 189 | 190 | 191 | doit=(Button)findViewById(R.id.doit); 192 | doit.setOnClickListener(new View.OnClickListener() { 193 | @Override 194 | public void onClick(View v) { 195 | new AlertDialog.Builder(DoActivity.this) 196 | .setTitle("选择数据") 197 | .setMessage("请确认要提交的里程数后再提交!\n"+ 198 | "跑步距离:"+Distence+'\n'+ 199 | "跑步速度:"+Pace+"\n"+ 200 | "迈步频率:"+Stride_frequncy) 201 | .setPositiveButton("确认", new DialogInterface.OnClickListener() { 202 | @Override 203 | public void onClick(DialogInterface dialog, int which) { 204 | Toast.makeText(DoActivity.this,"提交成功!",Toast.LENGTH_SHORT).show(); 205 | try { 206 | //获取Record 207 | InputStream inputStrean= getResources().getAssets().open("pace.json"); 208 | InputStreamReader inputStreamReader=new InputStreamReader(inputStrean); 209 | Record record=new Record(Distence,Pace,Stride_frequncy); 210 | record.Build(inputStreamReader); 211 | 212 | String resultRecord=record.getDetail(); 213 | System.out.println("Result:"+resultRecord); 214 | //新线程Upload 215 | UploadThread runUpload = new UploadThread(record,getUsername(),getToken()); 216 | runUpload.start(); 217 | 218 | 219 | } catch (IOException e) { 220 | e.printStackTrace(); 221 | } 222 | } 223 | }) 224 | .setNegativeButton("返回", new DialogInterface.OnClickListener() { 225 | @Override 226 | public void onClick(DialogInterface dialog, int which) { 227 | Toast.makeText(DoActivity.this,"重新选择!",Toast.LENGTH_SHORT).show(); 228 | } 229 | }) 230 | .show(); 231 | } 232 | }); 233 | } 234 | 235 | @Override 236 | public boolean onCreateOptionsMenu(Menu menu){ 237 | System.out.println(menu); 238 | getMenuInflater().inflate(R.menu.toolbar,menu); 239 | return true; 240 | } 241 | 242 | @Override 243 | public boolean onOptionsItemSelected(MenuItem item){ 244 | switch (item.getItemId()){ 245 | case android.R.id.home: 246 | mdrawerLayout.openDrawer(GravityCompat.START); 247 | break; 248 | default: 249 | } 250 | return true; 251 | } 252 | 253 | @Override 254 | public void onBackPressed(){ 255 | moveTaskToBack(true); 256 | } 257 | 258 | } 259 | 260 | class UploadThread extends Thread { 261 | private Record resultRecord; 262 | private String username; 263 | private String token; 264 | 265 | public UploadThread(Record resultRecord,String username,String token) { 266 | this.username=username; 267 | this.resultRecord=resultRecord; 268 | this.token=token; 269 | } 270 | public void run() { 271 | try { 272 | upload(this.resultRecord); 273 | } catch (Exception e) { 274 | e.printStackTrace(); 275 | } 276 | } 277 | 278 | public void upload(Record resultRecord) { 279 | Connection con = Jsoup.connect("https://pkunewyouth.pku.edu.cn/record/"+this.username); 280 | //遍历生成参数 281 | con.data("userId",this.username); 282 | con.data("duration",resultRecord.getDuration()); 283 | con.data("data",resultRecord.getData()); 284 | con.data("detail", resultRecord.getDetail()); 285 | con.data("misc","{\"agent\": \"Android v1.2+\"}"); 286 | con.data("step",resultRecord.getStep()); 287 | 288 | con.header("User-Agent", "okhttp/3.10.0"); 289 | con.header("Authorization",this.token); 290 | 291 | Document doc = null; 292 | try { 293 | doc = con.post(); 294 | } catch (IOException e) { 295 | System.out.println("upload error"); 296 | } 297 | String htmlResult=doc.html(); 298 | System.out.println(htmlResult); 299 | } 300 | // public String getRunResult() { 301 | // if (this.token.contains("错误") || this.token.contains("err")){ 302 | // return "POSTERR"; 303 | // } 304 | // return this.token; 305 | // } 306 | } 307 | 308 | class WeatherThread extends Thread { 309 | public String res; 310 | public void run() { 311 | try { 312 | getWeather(); 313 | } catch (Exception e) { 314 | e.printStackTrace(); 315 | } 316 | 317 | } 318 | public String weather(){ 319 | return res; 320 | } 321 | 322 | public void getWeather() { 323 | Connection con = Jsoup.connect("https://pkunewyouth.pku.edu.cn/weather/all"); 324 | 325 | con.header("User-Agent", "okhttp/3.10.0"); 326 | 327 | Document doc = null; 328 | try { 329 | doc = con.get(); 330 | } catch (IOException e) { 331 | System.out.println("upload error"); 332 | this.res="本学期暂未开始跑步!"; 333 | return; 334 | } 335 | String htmlResult=doc.html(); 336 | System.out.println(htmlResult); 337 | this.res=htmlResult; 338 | } 339 | } 340 | 341 | class UserThread extends Thread { 342 | private String username; 343 | private String token; 344 | private String res; 345 | 346 | public UserThread(String username,String token) { 347 | this.username=username; 348 | this.token=token; 349 | } 350 | public void run() { 351 | try { 352 | getUserData(); 353 | } catch (Exception e) { 354 | e.printStackTrace(); 355 | } 356 | } 357 | 358 | public String getRes(){ 359 | return res; 360 | } 361 | 362 | public void getUserData() { 363 | Connection con = Jsoup.connect("https://pkunewyouth.pku.edu.cn/record/status/"+this.username); 364 | 365 | con.header("User-Agent", "okhttp/3.10.0"); 366 | con.header("Authorization",this.token); 367 | 368 | Document doc = null; 369 | try { 370 | doc = con.get(); 371 | } catch (IOException e) { 372 | System.out.println("upload error"); 373 | this.res="本学期暂未开始跑步!"; 374 | return; 375 | } 376 | String htmlResult=doc.html(); 377 | System.out.println(htmlResult); 378 | this.res=htmlResult; 379 | } 380 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/pkuhelper/LoginActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | 7 | public class LoginActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_login); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/pkuhelper/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import androidx.appcompat.app.ActionBar; 4 | import androidx.appcompat.app.AlertDialog; 5 | import androidx.appcompat.app.AppCompatActivity; 6 | import androidx.appcompat.widget.Toolbar; 7 | import androidx.drawerlayout.widget.DrawerLayout; 8 | 9 | import android.content.DialogInterface; 10 | import android.content.Intent; 11 | import android.media.MediaPlayer; 12 | import android.net.Uri; 13 | import android.os.Bundle; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.widget.Button; 17 | import android.widget.EditText; 18 | import android.widget.TextView; 19 | import android.widget.Toast; 20 | 21 | import org.jsoup.Connection; 22 | import org.jsoup.Jsoup; 23 | import org.jsoup.nodes.Document; 24 | 25 | import java.io.IOException; 26 | import java.security.MessageDigest; 27 | import java.security.NoSuchAlgorithmException; 28 | import java.util.Comparator; 29 | import java.util.Map; 30 | import java.util.TreeMap; 31 | 32 | public class MainActivity extends AppCompatActivity { 33 | 34 | private CustomVideoView welcome_video; 35 | private Button welcome_btn; 36 | private TextView Policy; 37 | 38 | 39 | private String AppID; 40 | private String AppSecret; 41 | private String Cache_AccessToken; 42 | private int Token_Expired; 43 | private Map mp; 44 | 45 | 46 | @Override 47 | protected void onCreate(Bundle savedInstanceState) { 48 | super.onCreate(savedInstanceState); 49 | setContentView(R.layout.activity_main); 50 | 51 | 52 | 53 | welcome_video = (CustomVideoView) findViewById(R.id.welcome_video); 54 | final String url = "android.resource://" + getPackageName() + "/" + R.raw.welcome_start; 55 | System.out.println(url); 56 | welcome_video.setVideoURI(Uri.parse(url)); 57 | welcome_video.start(); 58 | welcome_video.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { 59 | @Override 60 | public void onCompletion(MediaPlayer mp) { 61 | welcome_video.start(); 62 | } 63 | }); 64 | 65 | Policy=(TextView)findViewById(R.id.POLICY); 66 | Policy.setOnClickListener(new View.OnClickListener() { 67 | @Override 68 | public void onClick(View v) { 69 | new AlertDialog.Builder(MainActivity.this) 70 | .setTitle("使用须知") 71 | .setMessage("1.该移动应用不会搜集任何个人身份识别资料,使用IAAA只为RUNNER鉴权。\n\n"+ 72 | "2.该移动应用只为学习研究PKURUNNER传输原理,无其他任何用途。\n\n"+ 73 | "3.目前为测试版本。\n\n"+ 74 | "4.制作人员:周周 李缺酒\n\n"+ 75 | "5.出现任何问题请联系邮箱1247905338@qq.com") 76 | .setPositiveButton("已阅", new DialogInterface.OnClickListener() { 77 | @Override 78 | public void onClick(DialogInterface dialog, int which) { 79 | 80 | } 81 | }).show(); 82 | } 83 | }); 84 | 85 | welcome_btn = (Button) findViewById(R.id.welcome_btn); 86 | welcome_btn.setOnClickListener(new View.OnClickListener() { 87 | @Override 88 | public void onClick(View v) { 89 | if (!welcome_video.isPlaying()) { 90 | welcome_video.start(); 91 | } 92 | AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); 93 | View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.activity_login, null); 94 | final EditText username = (EditText) view.findViewById(R.id.username); 95 | final EditText password = (EditText) view.findViewById(R.id.password); 96 | 97 | AppID = "PKU_Runner"; 98 | AppSecret = "7696baa1fa4ed9679441764a271e556e"; // 或者说 salt 99 | Cache_AccessToken = "PKURunner_AccessToken.json"; 100 | Token_Expired = 3600 * 3;// token 缓存 3 小时 101 | 102 | mp = new TreeMap<>(new Comparator() { 103 | @Override 104 | public int compare(String str1, String str2) { 105 | return str1.compareTo(str2); 106 | } 107 | }); 108 | 109 | 110 | Button button = (Button) view.findViewById(R.id.login); 111 | button.setOnClickListener(new View.OnClickListener() { 112 | @Override 113 | public void onClick(View v) { 114 | //发起登录 115 | mp.put("appId", AppID); 116 | mp.put("randCode", ""); 117 | mp.put("smsCode", "SMS"); 118 | mp.put("otpCode", ""); 119 | mp.put("userName", username.getText().toString()); 120 | mp.put("password", password.getText().toString()); 121 | 122 | RunThread runT = new RunThread(mp); 123 | runT.start(); 124 | try { 125 | runT.join(); 126 | } catch (InterruptedException e) { 127 | e.printStackTrace(); 128 | } 129 | 130 | mp.clear(); 131 | 132 | String token=runT.getRunResult(); 133 | if (!token.equals("POSTERR")){ 134 | Toast.makeText(MainActivity.this, "鉴权成功!", Toast.LENGTH_SHORT).show(); 135 | 136 | //跳转主页面 137 | Intent intent=new Intent(MainActivity.this,DoActivity.class); 138 | intent.putExtra("username", username.getText().toString()); 139 | intent.putExtra("token",token); 140 | startActivity(intent); 141 | finish(); 142 | }else { 143 | Toast.makeText(MainActivity.this, "IAAA鉴权失败!", Toast.LENGTH_SHORT).show(); 144 | } 145 | 146 | } 147 | }); 148 | 149 | builder.setView(view).show(); 150 | } 151 | }); 152 | } 153 | 154 | 155 | 156 | } 157 | class RunThread extends Thread { 158 | private String token=null; 159 | private Map mp; 160 | private String mpMD5; 161 | 162 | public RunThread(Map mp) { 163 | this.mp = mp; 164 | } 165 | public void run() { 166 | try { 167 | this.token=Login(this.mp); 168 | } catch (Exception e) { 169 | e.printStackTrace(); 170 | } 171 | } 172 | private String getAppSecret() { 173 | return "7696baa1fa4ed9679441764a271e556e"; 174 | } 175 | 176 | private String md5(Map mp) { 177 | //MD5("&".join("=".join(item) for item in sorted(payload.items())) + self.AppSecret) # TreeMap 按 keys 升序遍历 178 | //String content=null; 179 | StringBuffer str = new StringBuffer(); 180 | for (Map.Entry entry : mp.entrySet()) { 181 | String mapKey = entry.getKey(); 182 | String mapValue = entry.getValue(); 183 | 184 | str.append(mapKey); 185 | str.append("="); 186 | str.append(mapValue); 187 | str.append("&"); 188 | } 189 | str.deleteCharAt(str.length()-1); 190 | String content = "" + str + getAppSecret(); 191 | System.out.println("content:"+content); 192 | 193 | 194 | byte[] hash; 195 | try { 196 | hash = MessageDigest.getInstance("MD5").digest(content.getBytes()); 197 | } catch (NoSuchAlgorithmException e) { 198 | throw new RuntimeException("NoSuchAlgorithmException", e); 199 | } 200 | 201 | StringBuilder hex = new StringBuilder(hash.length * 2); 202 | for (byte b : hash) { 203 | if ((b & 0xFF) < 0x10) { 204 | hex.append(0); 205 | } 206 | hex.append(Integer.toHexString(b & 0xff)); 207 | } 208 | 209 | return hex.toString(); 210 | } 211 | public String Login(Map mp) { 212 | mpMD5 = md5(mp); 213 | System.out.println("msgAbs"+mpMD5); 214 | mp.put("msgAbs", mpMD5); 215 | 216 | 217 | Connection con = Jsoup.connect("https://iaaa.pku.edu.cn/iaaa/svc/authen/login.do"); 218 | //遍历生成参数 219 | for (Map.Entry entry : mp.entrySet()) { 220 | //添加参数 221 | con.data(entry.getKey(), entry.getValue()); 222 | con.header("User-Agent", "Dalvik/2.1.0 (Linux; U; Android 8.0.0; MI 5 MIUI/V10.0.1.0.OAACNFH)"); 223 | } 224 | Document doc = null; 225 | try { 226 | doc = con.post(); 227 | } catch (IOException e) { 228 | return "POSTERR"; 229 | } 230 | String token=doc.body().text(); 231 | System.out.println(token); 232 | token=token.substring(25,token.length()-2); 233 | System.out.println(token); 234 | return token; 235 | } 236 | public String getRunResult() { 237 | if (this.token.contains("错误") || this.token.contains("err")){ 238 | return "POSTERR"; 239 | } 240 | return this.token; 241 | } 242 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/pkuhelper/Record.java: -------------------------------------------------------------------------------- 1 | package com.example.pkuhelper; 2 | 3 | import android.annotation.SuppressLint; 4 | 5 | import com.google.gson.JsonArray; 6 | import com.google.gson.JsonObject; 7 | import com.google.gson.JsonParser; 8 | 9 | import java.io.FileNotFoundException; 10 | import java.io.InputStreamReader; 11 | import java.text.SimpleDateFormat; 12 | import java.util.ArrayList; 13 | import java.util.Date; 14 | import java.util.Random; 15 | 16 | public class Record { 17 | private double Distance; 18 | private double Pace; 19 | private double Frequency; 20 | private double Distance_Per_Loop = 0.45; 21 | 22 | private int duration=0; 23 | private String data; 24 | private int step; 25 | private ArrayList> detail = new ArrayList>(); 26 | public String getDuration(){ 27 | return ""+this.duration; 28 | } 29 | public String getData(){ 30 | return this.data; 31 | } 32 | public String getStep(){ 33 | return ""+this.step; 34 | } 35 | public String getDetail(){ 36 | return ""+this.detail; 37 | } 38 | 39 | public Record(double Distance,double Pace,double Frequency) throws FileNotFoundException { 40 | this.Distance=Distance; 41 | this.Pace=Pace; 42 | this.Frequency=Frequency; 43 | } 44 | 45 | public String getDate(){ 46 | @SuppressLint("SimpleDateFormat") SimpleDateFormat formatter = new SimpleDateFormat ("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'"); 47 | Date curDate = new Date(System.currentTimeMillis());//获取当前时间 48 | String str = formatter.format(curDate); 49 | return str; 50 | } 51 | public double getPointDelta(){ 52 | Random rand=new Random(); 53 | double num = (rand.nextDouble()-0.5)*2*0.000015; 54 | return num; 55 | } 56 | 57 | public double getPaceDelta(){ 58 | Random rand=new Random(); 59 | double num = (rand.nextDouble()-0.5)*2*0.1; 60 | return num; 61 | } 62 | 63 | public int getFrequencyDelta(){ 64 | Random rand=new Random(); 65 | double num = (rand.nextDouble()-0.5)*2*15; 66 | return (int)num; 67 | } 68 | 69 | public void point_generator(JsonArray points_per_loop){ 70 | int points_num_per_loop=(int)(0.4*this.Pace*60); 71 | 72 | if (points_num_per_loop>points_per_loop.size()){ 73 | System.out.println("'pace' ERROR"); 74 | } 75 | 76 | double total_loop=this.Distance/0.4; 77 | double current_loop=0.0; 78 | 79 | while(current_loop point_two = new ArrayList(); 86 | double p0=point.get(0).getAsDouble()+getPointDelta(); 87 | double p1=point.get(1).getAsDouble()+getPointDelta(); 88 | point_two.add(p0); 89 | point_two.add(p1); 90 | point_two.add((double)0); 91 | this.detail.add(point_two); 92 | 93 | current_loop=current_loop+(1.0/points_num_per_loop); 94 | System.out.println(current_loop); 95 | if(current_loop>=total_loop){ 96 | break; 97 | } 98 | } 99 | } 100 | } 101 | 102 | public static JsonArray getJson(InputStreamReader inputStreamReader) throws FileNotFoundException { 103 | JsonParser parser=new JsonParser(); 104 | JsonObject object=(JsonObject)parser.parse(inputStreamReader); 105 | //转化为数组 106 | return object.get("data").getAsJsonArray(); 107 | } 108 | 109 | public void Build(InputStreamReader inputStreamReader) throws FileNotFoundException { 110 | JsonArray jsonArray=getJson(inputStreamReader); 111 | System.out.println("jsonarray:"+jsonArray); 112 | this.data=getDate(); 113 | this.duration=(int)(this.Distance*this.Distance_Per_Loop/0.4*(this.Pace+this.getPaceDelta())*60); 114 | this.step=(int)((this.Frequency+getFrequencyDelta())*this.duration/60); 115 | 116 | point_generator(jsonArray); 117 | } 118 | 119 | 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/all.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/bk.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/bussiness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/bussiness.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/down.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/flag.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/man.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/man.jpeg -------------------------------------------------------------------------------- /app/src/main/res/drawable/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/map.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/normal_btn.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LoseNine/PKURunnerHelper/abc73920f398cff2faa056c450f29da4fb78c984/app/src/main/res/drawable/weather.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_do.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 20 | 21 | 27 | 28 | 29 | 43 | 44 | 45 | 50 | 51 | 58 | 59 | 67 | 68 | 75 | 76 | 83 | 84 | 91 | 92 | 99 | 100 | 101 | 102 |