├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
└── workflows
│ └── lock-issue-and-delete-comment.yml
├── .gitignore
├── AppIdMap.txt
├── LICENSE
├── README.md
├── app
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── xposed_init
│ ├── java
│ └── pansong291
│ │ └── xposed
│ │ └── quickenergy
│ │ ├── AntCooperate.java
│ │ ├── AntFarm.java
│ │ ├── AntForest.java
│ │ ├── AntForestNotification.java
│ │ ├── AntForestToast.java
│ │ ├── AntMember.java
│ │ ├── AntSports.java
│ │ ├── KBMember.java
│ │ ├── hook
│ │ ├── AntCooperateRpcCall.java
│ │ ├── AntFarmRpcCall.java
│ │ ├── AntForestRpcCall.java
│ │ ├── AntMemberRpcCall.java
│ │ ├── AntSportsRpcCall.java
│ │ ├── ClassMember.java
│ │ ├── KBMemberRpcCall.java
│ │ ├── RpcCall.java
│ │ └── XposedHook.java
│ │ ├── ui
│ │ ├── AlipayCooperate.java
│ │ ├── AlipayId.java
│ │ ├── AlipayUser.java
│ │ ├── ChoiceDialog.java
│ │ ├── EditDialog.java
│ │ ├── HtmlViewerActivity.java
│ │ ├── ListAdapter.java
│ │ ├── ListDialog.java
│ │ ├── MainActivity.java
│ │ ├── MyWebView.java
│ │ ├── OptionsAdapter.java
│ │ └── SettingsActivity.java
│ │ └── util
│ │ ├── Config.java
│ │ ├── CooperationIdMap.java
│ │ ├── FileUtils.java
│ │ ├── FriendIdMap.java
│ │ ├── Log.java
│ │ ├── RandomUtils.java
│ │ └── Statistics.java
│ └── res
│ ├── drawable
│ └── button.xml
│ ├── layout
│ ├── activity_html_viewer.xml
│ ├── activity_main.xml
│ ├── activity_settings.xml
│ ├── dialog_list.xml
│ ├── include_settings.xml
│ └── list_item.xml
│ ├── values-v21
│ └── styles.xml
│ └── values
│ ├── arrays.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
└── settings.gradle
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug 反馈 / Bug report
3 | about: Create a report to help us improve
4 | title: 这是标题!This is the title!
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | [或许你遇到的问题已经在 wiki 里有说明了](https://github.com/pansong291/XQuickEnergy/wiki)
11 |
12 | [请先阅读此反馈 BUG 的注意事项,再提交](https://github.com/pansong291/XQuickEnergy/issues/25)
13 |
--------------------------------------------------------------------------------
/.github/workflows/lock-issue-and-delete-comment.yml:
--------------------------------------------------------------------------------
1 | name: Lock Issue And Delete Comment
2 |
3 | on:
4 | issues:
5 | types: [opened, edited, reopened]
6 | issue_comment:
7 | types: [created, edited]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | lock-and-delete:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: lock issue and delete comment
15 | uses: pansong291/issue-interceptor-action@main
16 | with:
17 | test-regex: ${{ secrets.REGEX_ISSUE_INTERCEPTOR }}
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # IntelliJ
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/assetWizardSettings.xml
41 | .idea/dictionaries
42 | .idea/libraries
43 | .idea/caches
44 |
45 | # Keystore files
46 | # Uncomment the following line if you do not want to check your keystore files in.
47 | #*.jks
48 |
49 | # External native build folder generated in Android Studio 2.2 and later
50 | .externalNativeBuild
51 |
52 | # Google Services (e.g. APIs or Firebase)
53 | google-services.json
54 |
55 | # Freeline
56 | freeline.py
57 | freeline/
58 | freeline_project_description.json
59 |
60 | # fastlane
61 | fastlane/report.xml
62 | fastlane/Preview.html
63 | fastlane/screenshots
64 | fastlane/test_output
65 | fastlane/readme.md
66 |
--------------------------------------------------------------------------------
/AppIdMap.txt:
--------------------------------------------------------------------------------
1 | 10000003:充值中心
2 | 10000009:爱心捐赠
3 | 20000001:null
4 | 20000003:账单
5 | 20000014:我的银行卡
6 | 20000019:余额
7 | 20000032:余额宝
8 | 20000033:余额提现
9 | 20000038:关联账户认证/身份认证
10 | 20000042:null
11 | 20000047:null
12 | 20000067:?
13 | 20000076:账单
14 | 20000111:?
15 | 20000120:饿了么外卖
16 | 20000123:个人收钱
17 | 20000134:股票
18 | 20000142:娱乐宝
19 | 20000160:支付宝会员
20 | 20000165:理财
21 | 20000180:借呗
22 | 20000193:生活缴费
23 | 20000199:花呗
24 | 20000218:黄金
25 | 20000241:车险服务
26 | 20000691:我的客服
27 | 20000725:设置
28 | 20000754:我的快递
29 | 20000793:基金
30 | 20000909:args error
31 | 20000936:蚂蚁保险
32 | 20001045:args error
33 | 60000002:蚂蚁森林
34 | 60000010:?
35 | 60000071:天天有料
36 | 60000081:商家服务
37 | 60000123:args error
38 | 60000127:args error
39 | 60000148:财富号
40 | 60000161:支付宝会员周周乐
41 | 63300018:?
42 | 66666673:风险测试/风险类型
43 | 66666674:蚂蚁庄园
44 | 66666698:标签系统/标签和随笔
45 | 66666708:余利宝
46 | 66666721:财富有料
47 | 66666735:基金组合
48 | 66666741:上证指数讨论区
49 | 66666755:好医保
50 | 66666783:爱攒油加油站
51 | 66666819:还贷管家
52 | 66666823:?
53 | 66666825:财富标签页/我的理财标签
54 | 66666828:知识课堂
55 | 66666866:收益曲线
56 | 66666883:网商贷
57 | 66666886:蚂蚁森林合种
58 | 66666897:工资理财
59 | 68686987:网贷
60 | 68687015:办理赔
61 | 68687031:智能理财助理
62 | 68687049:蚂蚁心愿
63 | 68687058:null
64 | 68687109:null
65 | 68687129:行走积分赛
66 | 68687131:养老金
67 | 68687158:支付宝积分猜涨跌
68 | 68687197:null
69 | 68687233:股票工具
70 | 68687242:尊享理财
71 | 68687249:大盘晴雨表
72 | 68687279:null
73 | 68687357:null
74 | 77700124:余额宝
75 | 77700126:互相宝
76 | 77700130:花呗账单
77 | 77700144:扫码点单
78 | 77700152:信用卡还款
79 | 77700173:标注高德地图(在高德地图上标注我的商铺)
80 | 77700174:财富王者
81 | 77700199:财富SHOW
82 | 77700223:笔笔攒
83 | 77700234:模拟炒股
84 | 77700252:市场投资情绪
85 | 77700253:资金管理
86 | 77700257:收钱有奖
87 | 77700279:校园生活
88 | 77700292:收入统计
89 | 77700296:?
90 | 98000012:?
91 | 2013062600000474:new
92 | 2016122804685366:new
93 | 2017081908285290:new
94 | 2018030502317554:new
95 | 2018040402504128:new
96 | 2018051160096372:new
97 | 2018052460226391:new
98 | 2018071160524903:new
99 | 2018091361395351:new
100 | 2018110662035452:new
101 | 2018110762040932:new
102 | 2018112962211021:new
103 | 2018122762703259:new
104 | 2019010462802084:new
105 | 2019012963182381:new
106 | 2019021363229455:new
107 | 2019030863479637:new
108 | 2019031563521845:new
109 | 2019032763709372:new
110 | 2019032863733398:new
111 | 2019040963856084:new
112 | 2019042364288308:new
113 | 2019060465478294:new
114 | 2019060565481471:new
115 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XQuickEnergy
2 |
3 | [](LICENSE)
4 | [](../../releases)
5 | [](../../releases)
6 |
7 | 快速收取蚂蚁森林能量
8 | 进入界面快速收取,非自动收取
9 | 更多详情请见[Wiki](../../wiki)
10 |
11 | 原地址:[https://github.com/yongjun925/autocollectenergy](https://github.com/yongjun925/autocollectenergy)
12 | 感谢编码美丽的四哥(@尼古拉斯·赵四)
13 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 21
5 | buildToolsVersion "21.1.0"
6 |
7 | defaultConfig {
8 | applicationId "pansong291.xposed.quickenergy"
9 | minSdkVersion 14
10 | targetSdkVersion 21
11 | versionCode 20191130
12 | versionName "1.2.7-temp.1"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | }
25 |
--------------------------------------------------------------------------------
/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 C:\tools\adt-bundle-windows-x86_64-20131030\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
17 |
18 |
21 |
22 |
25 |
26 |
29 |
30 |
32 |
34 |
35 |
36 |
37 |
41 |
42 |
44 |
46 |
47 |
48 |
49 |
52 |
53 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/assets/xposed_init:
--------------------------------------------------------------------------------
1 | pansong291.xposed.quickenergy.hook.XposedHook
2 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntCooperate.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import pansong291.xposed.quickenergy.hook.AntCooperateRpcCall;
6 | import pansong291.xposed.quickenergy.util.Config;
7 | import pansong291.xposed.quickenergy.util.CooperationIdMap;
8 | import pansong291.xposed.quickenergy.util.FriendIdMap;
9 | import pansong291.xposed.quickenergy.util.Log;
10 | import pansong291.xposed.quickenergy.util.RandomUtils;
11 | import pansong291.xposed.quickenergy.util.Statistics;
12 |
13 | public class AntCooperate
14 | {
15 | private static final String TAG = AntCooperate.class.getCanonicalName();
16 |
17 | public static void start(ClassLoader loader, int times)
18 | {
19 | if(!Config.cooperateWater() || times != 0)
20 | return;
21 | new Thread()
22 | {
23 | private ClassLoader loader;
24 |
25 | public Thread setData(ClassLoader cl)
26 | {
27 | loader = cl;
28 | return this;
29 | }
30 |
31 | @Override
32 | public void run()
33 | {
34 | try
35 | {
36 | while(FriendIdMap.currentUid == null || FriendIdMap.currentUid.isEmpty())
37 | Thread.sleep(100);
38 | String s = AntCooperateRpcCall.rpcCall_queryUserCooperatePlantList(loader);
39 | if(s == null)
40 | {
41 | Thread.sleep(RandomUtils.delay());
42 | s = AntCooperateRpcCall.rpcCall_queryUserCooperatePlantList(loader);
43 | }
44 | JSONObject jo = new JSONObject(s);
45 | if(jo.getString("resultCode").equals("SUCCESS"))
46 | {
47 | int userCurrentEnergy = jo.getInt("userCurrentEnergy");
48 | JSONArray ja = jo.getJSONArray("cooperatePlants");
49 | for(int i = 0; i < ja.length(); i++)
50 | {
51 | jo = ja.getJSONObject(i);
52 | String cooperationId = jo.getString("cooperationId");
53 | if(!jo.has("name"))
54 | {
55 | s = AntCooperateRpcCall.rpcCall_queryCooperatePlant(loader, cooperationId);
56 | jo = new JSONObject(s).getJSONObject("cooperatePlant");
57 | }
58 | String name = jo.getString("name");
59 | int waterDayLimit = jo.getInt("waterDayLimit");
60 | CooperationIdMap.putIdMap(cooperationId, name);
61 | if(!Statistics.canCooperateWaterToday(FriendIdMap.currentUid, cooperationId))
62 | continue;
63 | int index = -1;
64 | for(int j = 0; j < Config.getCooperateWaterList().size(); j++)
65 | {
66 | if(Config.getCooperateWaterList().get(j).equals(cooperationId))
67 | {
68 | index = j;
69 | break;
70 | }
71 | }
72 | if(index >= 0)
73 | {
74 | int num = Config.getcooperateWaterNumList().get(index);
75 | if(num > waterDayLimit)
76 | num = waterDayLimit;
77 | if(num > userCurrentEnergy)
78 | num = userCurrentEnergy;
79 | if(num > 0)
80 | cooperateWater(loader, FriendIdMap.currentUid, cooperationId, num, name);
81 | }
82 | }
83 | }else
84 | {
85 | Log.i(TAG, jo.getString("resultDesc"));
86 | }
87 | }catch(Throwable t)
88 | {
89 | Log.i(TAG, "start.run err:");
90 | Log.printStackTrace(TAG, t);
91 | }
92 | CooperationIdMap.saveIdMap();
93 | }
94 | }.setData(loader).start();
95 | }
96 |
97 | private static void cooperateWater(ClassLoader loader, String uid, String coopId, int count, String name)
98 | {
99 | try
100 | {
101 | String s = AntCooperateRpcCall.rpcCall_cooperateWater(loader, uid, coopId, count);
102 | JSONObject jo = new JSONObject(s);
103 | if(jo.getString("resultCode").equals("SUCCESS"))
104 | {
105 | Log.forest("合种【" + name + "】" + jo.getString("barrageText"));
106 | Statistics.cooperateWaterToday(FriendIdMap.currentUid, coopId);
107 | }else
108 | {
109 | Log.i(TAG, jo.getString("resultDesc"));
110 | }
111 | }catch(Throwable t)
112 | {
113 | Log.i(TAG, "cooperateWater err:");
114 | Log.printStackTrace(TAG, t);
115 | }
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntForest.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import pansong291.xposed.quickenergy.AntFarm.TaskStatus;
6 | import pansong291.xposed.quickenergy.AntForestNotification;
7 | import pansong291.xposed.quickenergy.hook.AntForestRpcCall;
8 | import pansong291.xposed.quickenergy.util.Config;
9 | import pansong291.xposed.quickenergy.util.FriendIdMap;
10 | import pansong291.xposed.quickenergy.util.Log;
11 | import pansong291.xposed.quickenergy.util.RandomUtils;
12 | import pansong291.xposed.quickenergy.util.Statistics;
13 |
14 | public class AntForest
15 | {
16 | private static final String TAG = AntForest.class.getCanonicalName();
17 | private static String selfId;
18 | private static int collectedEnergy = 0;
19 | private static int helpCollectedEnergy = 0;
20 | private static int totalCollected = 0;
21 | private static int totalHelpCollected = 0;
22 | private static int collectTaskCount = 0;
23 | public enum CollectStatus
24 | { AVAILABLE, WAITING, INSUFFICIENT, ROBBED }
25 | public enum TaskAwardType
26 | {
27 | BUBBLE_BOOST, DRESS;
28 | public static final CharSequence[] nickNames =
29 | {"时光加速器","装扮"};
30 | public CharSequence nickName()
31 | {
32 | return nickNames[ordinal()];
33 | }
34 | }
35 |
36 | private static long serverTime = -1;
37 | private static long offsetTime = -1;
38 | private static long laterTime = -1;
39 |
40 | private static void queryEnergyRanking(ClassLoader loader, String startPoint)
41 | {
42 | boolean hasMore = false;
43 | try
44 | {
45 | String s;
46 | JSONObject jo;
47 | do
48 | {
49 | s = AntForestRpcCall.rpcCall_queryEnergyRanking(loader, startPoint);
50 | jo = new JSONObject(s);
51 | if(jo.getString("resultCode").equals("SUCCESS"))
52 | {
53 | hasMore = jo.getBoolean("hasMore");
54 | startPoint = jo.getString("nextStartPoint");
55 | JSONArray jaFriendRanking = jo.getJSONArray("friendRanking");
56 | for(int i = 0; i < jaFriendRanking.length(); i++)
57 | {
58 | jo = jaFriendRanking.getJSONObject(i);
59 | boolean optBoolean = jo.getBoolean("canCollectEnergy")
60 | || jo.getBoolean("canHelpCollect") || jo.getLong("canCollectLaterTime") > 0;
61 | String userId = jo.getString("userId");
62 | if(optBoolean && !userId.equals(selfId))
63 | {
64 | canCollectEnergy(loader, userId, true);
65 | }else
66 | {
67 | FriendIdMap.getNameById(userId);
68 | }
69 | }
70 | }else
71 | {
72 | Log.recordLog(jo.getString("resultDesc"), s);
73 | }
74 | }while(hasMore);
75 | }catch(Throwable t)
76 | {
77 | Log.i(TAG, "queryEnergyRanking err:");
78 | Log.printStackTrace(TAG, t);
79 | }
80 | onForestEnd(loader);
81 | }
82 |
83 | private static void canCollectSelfEnergy(ClassLoader loader, int times)
84 | {
85 | try
86 | {
87 | while(FriendIdMap.currentUid == null || FriendIdMap.currentUid.isEmpty())
88 | Thread.sleep(100);
89 | long start = System.currentTimeMillis();
90 | String s = AntForestRpcCall.rpcCall_queryNextAction(loader, FriendIdMap.currentUid);
91 | long end = System.currentTimeMillis();
92 | if(s == null)
93 | {
94 | Thread.sleep(RandomUtils.delay());
95 | start = System.currentTimeMillis();
96 | s = AntForestRpcCall.rpcCall_queryNextAction(loader, FriendIdMap.currentUid);
97 | end = System.currentTimeMillis();
98 | }
99 | JSONObject jo = new JSONObject(s);
100 | if(jo.getString("resultCode").equals("SUCCESS"))
101 | {
102 | serverTime = jo.getLong("now");
103 | offsetTime = (start + end) / 2 - serverTime;
104 | Log.i(TAG, "服务器时间:" + serverTime + ",本地减服务器时间差:" + offsetTime);
105 | JSONArray jaBubbles = jo.getJSONArray("bubbles");
106 | jo = jo.getJSONObject("userEnergy");
107 | selfId = jo.getString("userId");
108 | FriendIdMap.currentUid = selfId;
109 | String selfName = jo.getString("displayName");
110 | if(selfName == null || selfName.isEmpty())
111 | selfName = "我";
112 | FriendIdMap.putIdMap(selfId, selfName);
113 | Log.recordLog("进入【" + selfName + "】的蚂蚁森林", "");
114 | FriendIdMap.saveIdMap();
115 | if(Config.collectEnergy())
116 | for(int i = 0; i < jaBubbles.length(); i++)
117 | {
118 | jo = jaBubbles.getJSONObject(i);
119 | long bubbleId = jo.getLong("id");
120 | switch(CollectStatus.valueOf(jo.getString("collectStatus")))
121 | {
122 | case AVAILABLE:
123 | if(Config.getDontCollectList().contains(selfId))
124 | Log.recordLog("不偷取【" + selfName + "】", ", userId=" + selfId);
125 | else
126 | collectedEnergy += collectEnergy(loader, selfId, bubbleId, selfName, null);
127 | break;
128 |
129 | case WAITING:
130 | if(Config.getDontCollectList().contains(selfId))
131 | break;
132 | long produceTime = jo.getLong("produceTime");
133 | if(produceTime - serverTime < Config.checkInterval())
134 | execute(loader, selfName, selfId, null, bubbleId, produceTime);
135 | else
136 | setLaterTime(produceTime);
137 | break;
138 | }
139 | }
140 | }else
141 | {
142 | Log.recordLog(jo.getString("resultDesc"), s);
143 | }
144 | if(times == 0)
145 | {
146 | receiveTaskAward(loader);
147 | for(int i = 0; i < Config.getWaterFriendList().size(); i++)
148 | {
149 | String uid = Config.getWaterFriendList().get(i);
150 | if(selfId.equals(uid)) continue;
151 | int waterCount = Config.getWaterCountList().get(i);
152 | if(waterCount <= 0) continue;
153 | if(waterCount > 3) waterCount = 3;
154 | if(Statistics.canWaterFriendToday(uid, waterCount))
155 | waterFriendEnergy(loader, uid, waterCount);
156 | }
157 | checkUnknownId(loader);
158 | }
159 | }catch(Throwable t)
160 | {
161 | Log.i(TAG, "canCollectSelfEnergy err:");
162 | Log.printStackTrace(TAG, t);
163 | }
164 | }
165 |
166 | private static void canCollectEnergy(ClassLoader loader, String userId, boolean laterCollect)
167 | {
168 | try
169 | {
170 | long start = System.currentTimeMillis();
171 | String s = AntForestRpcCall.rpcCall_queryNextAction(loader, userId);
172 | long end = System.currentTimeMillis();
173 | JSONObject jo = new JSONObject(s);
174 | if(jo.getString("resultCode").equals("SUCCESS"))
175 | {
176 | serverTime = jo.getLong("now");
177 | offsetTime = (start + end) / 2 - serverTime;
178 | Log.i(TAG, "服务器时间:" + serverTime + ",本地减服务器时间差:" + offsetTime);
179 | String bizNo = jo.getString("bizNo");
180 | JSONArray jaProps = jo.getJSONArray("usingUserProps");
181 | JSONArray jaBubbles = jo.getJSONArray("bubbles");
182 | jo = jo.getJSONObject("userEnergy");
183 | String userName = jo.getString("displayName");
184 | if(userName == null || userName.isEmpty())
185 | userName = "*null*";
186 | String loginId = userName;
187 | if(jo.has("loginId"))
188 | loginId += "(" + jo.getString("loginId") + ")";
189 | FriendIdMap.putIdMap(userId, loginId);
190 | Log.recordLog("进入【" + loginId + "】的蚂蚁森林", "");
191 | FriendIdMap.saveIdMap();
192 | for(int i = 0; i < jaProps.length(); i++)
193 | {
194 | JSONObject joProps = jaProps.getJSONObject(i);
195 | if("energyShield".equals(joProps.getString("type")))
196 | {
197 | if(joProps.getLong("endTime") > serverTime)
198 | {
199 | Log.recordLog("【" + userName + "】被能量罩保护着哟", "");
200 | return;
201 | }
202 | }
203 | }
204 | int collected = 0;
205 | int helped = 0;
206 | for(int i = 0; i < jaBubbles.length(); i++)
207 | {
208 | jo = jaBubbles.getJSONObject(i);
209 | long bubbleId = jo.getLong("id");
210 | switch(CollectStatus.valueOf(jo.getString("collectStatus")))
211 | {
212 | case AVAILABLE:
213 | if(Config.getDontCollectList().contains(userId))
214 | Log.recordLog("不偷取【" + userName + "】", ", userId=" + userId);
215 | else
216 | collected += collectEnergy(loader, userId, bubbleId, userName, bizNo);
217 | break;
218 |
219 | case WAITING:
220 | if(!laterCollect || Config.getDontCollectList().contains(userId))
221 | break;
222 | long produceTime = jo.getLong("produceTime");
223 | if(produceTime - serverTime < Config.checkInterval())
224 | execute(loader, userName, userId, bizNo, bubbleId, produceTime);
225 | else
226 | setLaterTime(produceTime);
227 | break;
228 | }
229 | if(jo.getBoolean("canHelpCollect"))
230 | {
231 | if(Config.helpFriendCollect())
232 | {
233 | if(Config.getDontHelpCollectList().contains(userId))
234 | Log.recordLog("不帮收【" + userName + "】", ", userId=" + userId);
235 | else
236 | helped += forFriendCollectEnergy(loader, userId, bubbleId, userName);
237 | }else
238 | Log.recordLog("不帮收【" + userName + "】", ", userId=" + userId);
239 | }
240 | }
241 | if(helped > 0)
242 | {
243 | canCollectEnergy(loader, userId, false);
244 | }
245 | collectedEnergy += collected;
246 | }else
247 | {
248 | Log.recordLog(jo.getString("resultDesc"), s);
249 | }
250 | }catch(Throwable t)
251 | {
252 | Log.i(TAG, "canCollectEnergy err:");
253 | Log.printStackTrace(TAG, t);
254 | }
255 | }
256 |
257 | private static int collectEnergy(ClassLoader loader, String userId, long bubbleId, String userName, String bizNo)
258 | {
259 | int collected = 0;
260 | try
261 | {
262 | String s = AntForestRpcCall.rpcCall_collectEnergy(loader, userId, bubbleId);
263 | JSONObject jo = new JSONObject(s);
264 | if(jo.getString("resultCode").equals("SUCCESS"))
265 | {
266 | JSONArray jaBubbles = jo.getJSONArray("bubbles");
267 | for(int i = 0; i < jaBubbles.length(); i++)
268 | {
269 | jo = jaBubbles.getJSONObject(i);
270 | collected += jo.getInt("collectedEnergy");
271 | }
272 | if(collected > 0)
273 | {
274 | totalCollected += collected;
275 | Statistics.addData(Statistics.DataType.COLLECTED, collected);
276 | String str = "偷取【" + userName + "】的能量【" + collected + "克】";
277 | Log.forest(str);
278 | AntForestToast.show(str);
279 | }else
280 | {
281 | Log.recordLog("偷取【" + userName + "】的能量失败", ",UserID:" + userId + ",BubbleId:" + bubbleId);
282 | }
283 | if(bizNo == null || bizNo.isEmpty())
284 | return collected;
285 | int returnCount = 0;
286 | if(Config.returnWater30() > 0 && collected >= Config.returnWater30())
287 | returnCount = 3;
288 | else if(Config.returnWater20() > 0 && collected >= Config.returnWater20())
289 | returnCount = 2;
290 | else if(Config.returnWater10() > 0 && collected >= Config.returnWater10())
291 | returnCount = 1;
292 | if(returnCount > 0)
293 | returnFriendWater(loader, userId, userName, bizNo, returnCount);
294 | }else
295 | {
296 | Log.recordLog("【" + userName + "】" + jo.getString("resultDesc"), s);
297 | }
298 | }catch(Throwable t)
299 | {
300 | Log.i(TAG, "collectEnergy err:");
301 | Log.printStackTrace(TAG, t);
302 | }
303 | return collected;
304 | }
305 |
306 | private static int forFriendCollectEnergy(ClassLoader loader, String targetUserId, long bubbleId, String userName)
307 | {
308 | int helped = 0;
309 | try
310 | {
311 | String s = AntForestRpcCall.rpcCall_forFriendCollectEnergy(loader, targetUserId, bubbleId);
312 | JSONObject jo = new JSONObject(s);
313 | if(jo.getString("resultCode").equals("SUCCESS"))
314 | {
315 | JSONArray jaBubbles = jo.getJSONArray("bubbles");
316 | for(int i = 0; i < jaBubbles.length(); i++)
317 | {
318 | jo = jaBubbles.getJSONObject(i);
319 | helped += jo.getInt("collectedEnergy");
320 | }
321 | if(helped > 0)
322 | {
323 | Log.forest("帮【" + userName + "】收取【" + helped + "克】");
324 | helpCollectedEnergy += helped;
325 | totalHelpCollected += helped;
326 | Statistics.addData(Statistics.DataType.HELPED, helped);
327 | }else
328 | {
329 | Log.recordLog("帮【" + userName + "】收取失败", ",UserID:" + targetUserId + ",BubbleId" + bubbleId);
330 | }
331 | }else
332 | {
333 | Log.recordLog("【" + userName + "】" + jo.getString("resultDesc"), s);
334 | }
335 | }catch(Throwable t)
336 | {
337 | Log.i(TAG, "forFriendCollectEnergy err:");
338 | Log.printStackTrace(TAG, t);
339 | }
340 | return helped;
341 | }
342 |
343 | private static void waterFriendEnergy(ClassLoader loader, String userId, int count)
344 | {
345 | try
346 | {
347 | String s = AntForestRpcCall.rpcCall_queryNextAction(loader, userId);
348 | JSONObject jo = new JSONObject(s);
349 | if(jo.getString("resultCode").equals("SUCCESS"))
350 | {
351 | String bizNo = jo.getString("bizNo");
352 | jo = jo.getJSONObject("userEnergy");
353 | String userName = jo.getString("displayName");
354 | count = returnFriendWater(loader, userId, userName, bizNo, count);
355 | if(count > 0) Statistics.waterFriendToday(userId, count);
356 | }else
357 | {
358 | Log.recordLog(jo.getString("resultDesc"), s);
359 | }
360 | }catch(Throwable t)
361 | {
362 | Log.i(TAG, "waterFriendEnergy err:");
363 | Log.printStackTrace(TAG, t);
364 | }
365 | }
366 |
367 | private static int returnFriendWater(ClassLoader loader, String userId, String userName, String bizNo, int count)
368 | {
369 | if(bizNo == null || bizNo.isEmpty()) return 0;
370 | int wateredTimes = 0;
371 | try
372 | {
373 | String s;
374 | JSONObject jo;
375 | for(int waterCount = 1; waterCount <= count; waterCount++)
376 | {
377 | s = AntForestRpcCall.rpcCall_transferEnergy(loader, userId, bizNo, waterCount);
378 | jo = new JSONObject(s);
379 | s = jo.getString("resultCode");
380 | if(s.equals("SUCCESS"))
381 | {
382 | s = jo.getJSONObject("treeEnergy").getString("currentEnergy");
383 | Log.forest("给【" + userName + "】浇水成功,剩余能量【" + s + "克】");
384 | wateredTimes++;
385 | Statistics.addData(Statistics.DataType.WATERED, 10);
386 | }else if(s.equals("WATERING_TIMES_LIMIT"))
387 | {
388 | Log.recordLog("今日给【" + userName + "】浇水已达上限", "");
389 | wateredTimes = 3;
390 | break;
391 | }else
392 | {
393 | Log.recordLog(jo.getString("resultDesc"), jo.toString());
394 | }
395 | Thread.sleep(2000);
396 | }
397 | }catch(Throwable t)
398 | {
399 | Log.i(TAG, "returnFriendWater err:");
400 | Log.printStackTrace(TAG, t);
401 | }
402 | return wateredTimes;
403 | }
404 |
405 | private static void receiveTaskAward(ClassLoader loader)
406 | {
407 | try
408 | {
409 | String s = AntForestRpcCall.rpcCall_queryTaskList(loader);
410 | JSONObject jo = new JSONObject(s);
411 | if(jo.getString("resultCode").equals("SUCCESS"))
412 | {
413 | JSONArray jaForestTaskVOList = jo.getJSONArray("forestTaskVOList");
414 | for(int i = 0; i < jaForestTaskVOList.length(); i++)
415 | {
416 | jo = jaForestTaskVOList.getJSONObject(i);
417 | if(TaskStatus.FINISHED.name().equals(jo.getString("taskStatus")))
418 | {
419 | String taskAwardTypeStr = jo.getString("awardType");
420 | String awardName = null;
421 | if(taskAwardTypeStr.endsWith(TaskAwardType.DRESS.name()))
422 | {
423 | awardName = TaskAwardType.DRESS.nickName().toString();
424 | }else if(TaskAwardType.BUBBLE_BOOST.name().equals(taskAwardTypeStr))
425 | {
426 | awardName = TaskAwardType.BUBBLE_BOOST.nickName().toString();
427 | }
428 | int awardCount = jo.getInt("awardCount");
429 | s = AntForestRpcCall.rpcCall_receiveTaskAward(loader, jo.getString("taskType"));
430 | jo = new JSONObject(s);
431 | s = jo.getString("desc");
432 | if(s.equals("SUCCESS"))
433 | Log.forest("已领取【" + awardCount + "个】【" + awardName + "】");
434 | else
435 | Log.recordLog("领取失败," + s, jo.toString());
436 | }
437 | }
438 | }else
439 | {
440 | Log.recordLog(jo.getString("resultDesc"), s);
441 | }
442 | }catch(Throwable t)
443 | {
444 | Log.i(TAG, "receiveTaskAward err:");
445 | Log.printStackTrace(TAG, t);
446 | }
447 | }
448 |
449 | private static void queryPropList(ClassLoader loader)
450 | {
451 | try
452 | {
453 | String s = AntForestRpcCall.rpcCall_queryTaskList(loader);
454 | JSONObject jo = new JSONObject(s);
455 | if(jo.getString("resultCode").equals("SUCCESS"))
456 | {
457 | JSONArray jaForestPropVOList = jo.getJSONArray("forestPropVOList");
458 | for(int i = 0; i < jaForestPropVOList.length(); i++)
459 | {
460 | jo = jaForestPropVOList.getJSONObject(i);
461 | if(TaskStatus.FINISHED.name().equals(jo.getString("taskStatus")))
462 | {
463 | String taskType = jo.getString("taskType");
464 |
465 | }
466 | }
467 | }else
468 | {
469 | Log.recordLog(jo.getString("resultDesc"), s);
470 | }
471 | }catch(Throwable t)
472 | {
473 | Log.i(TAG, "queryTaskList err:");
474 | Log.printStackTrace(TAG, t);
475 | }
476 | }
477 |
478 | private static void setLaterTime(long time)
479 | {
480 | Log.i(TAG, "能量成熟时间:" + time);
481 | if(time > serverTime && serverTime > 0
482 | && (laterTime < 0 || time < laterTime))
483 | {
484 | laterTime = time;
485 | Log.i(TAG, laterTime - serverTime + "ms 后能量成熟");
486 | }
487 | }
488 |
489 | private static void onForestEnd(ClassLoader loader)
490 | {
491 | Log.recordLog(
492 | "收【" + collectedEnergy + "克】,帮【"
493 | + helpCollectedEnergy + "克】,"
494 | + collectTaskCount + "个蹲点任务", "");
495 | FriendIdMap.saveIdMap();
496 | collectedEnergy = 0;
497 | helpCollectedEnergy = 0;
498 | if(Config.collectEnergy())
499 | {
500 | StringBuilder sb = new StringBuilder();
501 | sb.append(" 收:" + totalCollected + ",帮:" + totalHelpCollected);
502 | if(laterTime > 0)
503 | {
504 | sb.append(",下个:");
505 | long second = (laterTime - serverTime) / 1000;
506 | long minute = second / 60;
507 | second %= 60;
508 | long hour = minute / 60;
509 | minute %= 60;
510 | if(hour > 0) sb.append(hour + "时");
511 | if(minute > 0) sb.append(minute + "分");
512 | sb.append(second + "秒");
513 | }
514 | Log.recordLog(sb.toString(), "");
515 | AntForestNotification.setContentText(Log.getFormatTime() + sb.toString());
516 | }
517 | laterTime = -1;
518 | }
519 |
520 | public static void checkEnergyRanking(ClassLoader loader, int times)
521 | {
522 | Log.recordLog("定时检测开始", "");
523 | new Thread()
524 | {
525 | ClassLoader loader;
526 | int times;
527 |
528 | public Thread setData(ClassLoader cl, int i)
529 | {
530 | loader = cl;
531 | times = i;
532 | return this;
533 | }
534 |
535 | @Override
536 | public void run()
537 | {
538 | canCollectSelfEnergy(loader, times);
539 | if(Config.collectEnergy())
540 | queryEnergyRanking(loader, "1");
541 | }
542 | }.setData(loader, times).start();
543 | }
544 |
545 | public static void checkUnknownId(ClassLoader loader)
546 | {
547 | String[] unknownIds = FriendIdMap.getUnknownIds();
548 | if(unknownIds != null)
549 | {
550 | new Thread()
551 | {
552 | ClassLoader loader;
553 | String[] unknownIds;
554 | public Thread setData(ClassLoader cl, String[] ss)
555 | {
556 | loader = cl;unknownIds = ss;
557 | return this;
558 | }
559 |
560 | @Override
561 | public void run()
562 | {
563 | try
564 | {
565 | Log.i(TAG, "开始检查" + unknownIds.length + "个未知id");
566 | for(int i = 0; i < unknownIds.length; i++)
567 | {
568 | long start = System.currentTimeMillis();
569 | String s = AntForestRpcCall.rpcCall_queryNextAction(loader, unknownIds[i]);
570 | long end = System.currentTimeMillis();
571 | JSONObject jo = new JSONObject(s);
572 | if(jo.getString("resultCode").equals("SUCCESS"))
573 | {
574 | serverTime = jo.getLong("now");
575 | offsetTime = (start + end) / 2 - serverTime;
576 | Log.i(TAG, "服务器时间:" + serverTime + ",本地减服务器时间差:" + offsetTime);
577 | jo = jo.getJSONObject("userEnergy");
578 | String userName = jo.getString("displayName");
579 | if(userName == null || userName.isEmpty())
580 | userName = "*null*";
581 | String loginId = userName;
582 | if(jo.has("loginId"))
583 | loginId += "(" + jo.getString("loginId") + ")";
584 | FriendIdMap.putIdMap(unknownIds[i], loginId);
585 | Log.recordLog("进入【" + loginId + "】的蚂蚁森林", "");
586 | FriendIdMap.saveIdMap();
587 | }
588 | }
589 | }catch(Throwable t)
590 | {
591 | Log.i(TAG, "checkUnknownId.run err:");
592 | Log.printStackTrace(TAG, t);
593 | }
594 | }
595 | }.setData(loader, unknownIds).start();
596 | }
597 | }
598 |
599 | public static void execute(ClassLoader loader, String userName, String userId, String bizNo, long bubbleId, long produceTime)
600 | {
601 | for(int i = Config.threadCount(); i > 0; i--)
602 | {
603 | BubbleTimerTask btt = new BubbleTimerTask(loader, userName, userId, bizNo, bubbleId, produceTime);
604 | long delay = btt.getDelayTime();
605 | btt.start();
606 | collectTaskCount++;
607 | Log.recordLog(delay / 1000 + "秒后尝试收取能量", "");
608 | }
609 | }
610 |
611 | public static class BubbleTimerTask extends Thread
612 | {
613 | ClassLoader loader;
614 | String userName;
615 | String userId;
616 | String bizNo;
617 | long bubbleId;
618 | long produceTime;
619 | long sleep = 0;
620 |
621 | BubbleTimerTask(ClassLoader cl, String un, String ui, String bn, long bi, long pt)
622 | {
623 | loader = cl;
624 | userName = un;
625 | bizNo = bn;
626 | userId = ui;
627 | bubbleId = bi;
628 | produceTime = pt;
629 | }
630 |
631 | public long getDelayTime()
632 | {
633 | sleep = produceTime + offsetTime - System.currentTimeMillis() - Config.advanceTime();
634 | return sleep;
635 | }
636 |
637 | @Override
638 | public void run()
639 | {
640 | try
641 | {
642 | if(sleep > 0) sleep(sleep);
643 | Log.recordLog("【" + userName + "】蹲点收取开始" + collectTaskCount, "");
644 | collectTaskCount--;
645 | long time = System.currentTimeMillis();
646 | int collected = 0;
647 | while(System.currentTimeMillis() - time < Config.collectTimeout())
648 | {
649 | collected = collectEnergy(loader, userId, bubbleId, userName, bizNo);
650 | if(collected > 0) break;
651 | if(Config.collectInterval() > 0)
652 | sleep(Config.collectInterval());
653 | }
654 | }catch(Throwable t)
655 | {
656 | Log.i(TAG, "BubbleTimerTask.run err:");
657 | Log.printStackTrace(TAG, t);
658 | }
659 | String s = " 收:" + totalCollected + ",帮:" + totalHelpCollected;
660 | Log.recordLog(s, "");
661 | AntForestNotification.setContentText(Log.getFormatTime() + s);
662 | }
663 |
664 | }
665 |
666 | }
667 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntForestNotification.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import android.app.Notification;
4 | import android.app.NotificationChannel;
5 | import android.app.NotificationManager;
6 | import android.app.PendingIntent;
7 | import android.app.Service;
8 | import android.content.Context;
9 | import android.content.Intent;
10 | import android.net.Uri;
11 | import android.os.Build;
12 |
13 | public class AntForestNotification
14 | {
15 | public static final int ANTFOREST_NOTIFICATION_ID = 46;
16 | private static NotificationManager mNotifyManager;
17 | public static final String CHANNEL_ID = "pansong291.xposed.quickenergy.ANTFOREST_NOTIFY_CHANNEL";
18 | private static Notification mNotification;
19 | private static Notification.Builder builder;
20 | private static boolean isStart = false;
21 |
22 | private AntForestNotification()
23 | {}
24 |
25 | public static boolean isStart()
26 | {
27 | return isStart;
28 | }
29 |
30 | public static void start(Context context)
31 | {
32 | initNotification(context);
33 | if(!isStart)
34 | {
35 | if(context instanceof Service)
36 | ((Service)context).startForeground(ANTFOREST_NOTIFICATION_ID, mNotification);
37 | else
38 | getNotificationManager(context).notify(ANTFOREST_NOTIFICATION_ID, mNotification);
39 | isStart = true;
40 | }
41 | }
42 |
43 | public static void setContentText(CharSequence cs)
44 | {
45 | if(isStart)
46 | {
47 | mNotification = builder.setContentText(cs).build();
48 | if(mNotifyManager != null)
49 | mNotifyManager.notify(ANTFOREST_NOTIFICATION_ID, mNotification);
50 | }
51 | }
52 |
53 | public static void stop(Context context, boolean remove)
54 | {
55 | if(isStart)
56 | {
57 | if(context instanceof Service)
58 | ((Service)context).stopForeground(remove);
59 | else
60 | getNotificationManager(context).cancel(ANTFOREST_NOTIFICATION_ID);
61 | isStart = false;
62 | }
63 | }
64 |
65 | private static void initNotification(Context context)
66 | {
67 | if(mNotification == null)
68 | {
69 | Intent it = new Intent(Intent.ACTION_VIEW);
70 | it.setData(Uri.parse("alipays://platformapi/startapp?appId="));
71 | PendingIntent pi = PendingIntent.getActivity(context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT);
72 |
73 | if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
74 | {
75 | NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, "XQuickEnergy能量提醒", NotificationManager.IMPORTANCE_LOW);
76 | notificationChannel.enableLights(false);
77 | notificationChannel.enableVibration(false);
78 | notificationChannel.setShowBadge(false);
79 | getNotificationManager(context).createNotificationChannel(notificationChannel);
80 | builder = new Notification.Builder(context, CHANNEL_ID);
81 | }else
82 | {
83 | getNotificationManager(context);
84 | builder = new Notification.Builder(context)
85 | .setPriority(Notification.PRIORITY_LOW);
86 | }
87 | mNotification = builder
88 | .setSmallIcon(android.R.drawable.sym_def_app_icon)
89 | .setContentTitle("XQuickEnergy")
90 | .setContentText("开始检测能量")
91 | .setAutoCancel(false)
92 | .setContentIntent(pi)
93 | .build();
94 | }
95 | }
96 |
97 | private static NotificationManager getNotificationManager(Context context)
98 | {
99 | if(mNotifyManager == null)
100 | mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
101 | return mNotifyManager;
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntForestToast.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import android.content.Context;
4 | import android.widget.Toast;
5 | import pansong291.xposed.quickenergy.util.Config;
6 | import pansong291.xposed.quickenergy.util.Log;
7 | import pansong291.xposed.quickenergy.hook.XposedHook;
8 |
9 | public class AntForestToast
10 | {
11 | private static final String TAG = AntForestToast.class.getCanonicalName();
12 | public static Context context;
13 |
14 | public static void show(CharSequence cs)
15 | {
16 | try
17 | {
18 | if(context != null && Config.showToast())
19 | {
20 | XposedHook.handler.post(
21 | new Runnable()
22 | {
23 | CharSequence cs;
24 |
25 | public Runnable setData(CharSequence c)
26 | {
27 | cs = c;
28 | return this;
29 | }
30 |
31 | @Override
32 | public void run()
33 | {
34 | try
35 | {
36 | Toast.makeText(context, cs, 0).show();
37 | }catch(Throwable t)
38 | {
39 | Log.i(TAG, "show.run err:");
40 | Log.printStackTrace(TAG, t);
41 | }
42 | }
43 | }.setData(cs));
44 | }
45 | }catch(Throwable t)
46 | {
47 | Log.i(TAG, "show err:");
48 | Log.printStackTrace(TAG, t);
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntMember.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import pansong291.xposed.quickenergy.hook.AntMemberRpcCall;
6 | import pansong291.xposed.quickenergy.util.Log;
7 | import pansong291.xposed.quickenergy.util.Statistics;
8 | import pansong291.xposed.quickenergy.util.Config;
9 |
10 | public class AntMember
11 | {
12 | public static final String TAG = AntMember.class.getCanonicalName();
13 |
14 | public static void receivePoint(ClassLoader loader, int times)
15 | {
16 | if(!Config.receivePoint() || times != 0)
17 | return;
18 |
19 | new Thread()
20 | {
21 | ClassLoader loader;
22 |
23 | public Thread setData(ClassLoader cl)
24 | {
25 | loader = cl;
26 | return this;
27 | }
28 |
29 | @Override
30 | public void run()
31 | {
32 | try
33 | {
34 | if(Statistics.canMemberSignInToday())
35 | {
36 | String s = AntMemberRpcCall.rpcCall_memberSignin(loader);
37 | JSONObject jo = new JSONObject(s);
38 | if(jo.getString("resultCode").equals("SUCCESS"))
39 | {
40 | Log.other(
41 | "领取〈每日签到〉〈" + jo.getString("signinPoint") +
42 | "积分〉,已签到〈" + jo.getString("signinSumDay") + "天〉");
43 | Statistics.memberSignInToday();
44 | }else
45 | {
46 | Log.recordLog(jo.getString("resultDesc"), s);
47 | }
48 | }
49 | queryPointCert(loader, 1, 8);
50 | claimFamilyPoint(loader);
51 | }catch(Throwable t)
52 | {
53 | Log.i(TAG, "receivePoint.run err:");
54 | Log.printStackTrace(TAG, t);
55 | }
56 | }
57 | }.setData(loader).start();
58 | }
59 |
60 | private static void queryPointCert(ClassLoader loader, int page, int pageSize)
61 | {
62 | try
63 | {
64 | String s = AntMemberRpcCall.rpcCall_queryPointCert(loader, page, pageSize);
65 | JSONObject jo = new JSONObject(s);
66 | if(jo.getString("resultCode").equals("SUCCESS"))
67 | {
68 | boolean hasNextPage = jo.getBoolean("hasNextPage");
69 | JSONArray jaCertList = jo.getJSONArray("certList");
70 | for(int i = 0; i < jaCertList.length(); i++)
71 | {
72 | jo = jaCertList.getJSONObject(i);
73 | String bizTitle = jo.getString("bizTitle");
74 | String id = jo.getString("id");
75 | int pointAmount = jo.getInt("pointAmount");
76 | s = AntMemberRpcCall.rpcCall_receivePointByUser(loader, id);
77 | jo = new JSONObject(s);
78 | if(jo.getString("resultCode").equals("SUCCESS"))
79 | {
80 | Log.other("领取〈" + bizTitle + "〉〈" + pointAmount + "积分〉");
81 | }else
82 | {
83 | Log.recordLog(jo.getString("resultDesc"), s);
84 | }
85 | }
86 | if(hasNextPage)
87 | queryPointCert(loader, page + 1, pageSize);
88 | }else
89 | {
90 | Log.recordLog(jo.getString("resultDesc"), s);
91 | }
92 | }catch(Throwable t)
93 | {
94 | Log.i(TAG, "queryPointCert err:");
95 | Log.printStackTrace(TAG, t);
96 | }
97 | }
98 |
99 | private static void claimFamilyPoint(ClassLoader loader)
100 | {
101 | try
102 | {
103 | String s = AntMemberRpcCall.rpcCall_familySignin(loader);
104 | s = AntMemberRpcCall.rpcCall_familyHomepage(loader);
105 | JSONObject jo = new JSONObject(s);
106 | if(jo.getBoolean("success"))
107 | {
108 | jo = jo.getJSONObject("data");
109 | if(jo.getBoolean("success"))
110 | {
111 | jo = jo.getJSONObject("familyInfoView");
112 | String familyId = jo.getString("familyId");
113 | s = AntMemberRpcCall.rpcCall_queryFamilyPointCert(loader, familyId);
114 | jo = new JSONObject(s);
115 | if(jo.getBoolean("success"))
116 | {
117 | JSONArray ja = jo.getJSONArray("familyPointCertInfos");
118 | for(int i = 0; i < ja.length(); i++)
119 | {
120 | jo = ja.getJSONObject(i);
121 | String bizTitle = jo.getString("bizTitle");
122 | long certId = jo.getLong("certId");
123 | s = AntMemberRpcCall.rpcCall_claimFamilyPointCert(loader, certId, familyId);
124 | jo = new JSONObject(s);
125 | if(jo.getBoolean("success"))
126 | {
127 | Log.other("领取〈" + bizTitle + "〉〈" + jo.getInt("realPoint") + "家庭积分〉");
128 | }else
129 | {
130 | Log.recordLog(jo.getString("resultDesc"), s);
131 | }
132 | }
133 | }else
134 | {
135 | Log.recordLog(jo.getString("resultDesc"), s);
136 | }
137 | }
138 | }
139 | }catch(Throwable t)
140 | {
141 | Log.i(TAG, "claimFamilyPoint err:");
142 | Log.printStackTrace(TAG, t);
143 | }
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/AntSports.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import pansong291.xposed.quickenergy.hook.AntSportsRpcCall;
6 | import pansong291.xposed.quickenergy.util.Config;
7 | import pansong291.xposed.quickenergy.util.FriendIdMap;
8 | import pansong291.xposed.quickenergy.util.Log;
9 | import pansong291.xposed.quickenergy.util.RandomUtils;
10 | import pansong291.xposed.quickenergy.util.Statistics;
11 |
12 | public class AntSports
13 | {
14 | private static final String TAG = AntSports.class.getCanonicalName();
15 |
16 | public static void start(ClassLoader loader, int times)
17 | {
18 | new Thread()
19 | {
20 | ClassLoader loader;
21 | int times;
22 |
23 | public Thread setData(ClassLoader cl, int i)
24 | {
25 | loader = cl;
26 | times = i;
27 | return this;
28 | }
29 |
30 | @Override
31 | public void run()
32 | {
33 | try
34 | {
35 | if(Config.openTreasureBox())
36 | queryMyHomePage(loader);
37 | if(Config.donateCharityCoin())
38 | queryProjectList(loader);
39 | if(Config.minExchangeCount() > 0 && Statistics.canExchangeToday() && times == 0)
40 | queryWalkStep(loader);
41 | }catch(Throwable t)
42 | {
43 | Log.i(TAG, "start.run err:");
44 | Log.printStackTrace(TAG, t);
45 | }
46 | }
47 | }.setData(loader, times).start();
48 | }
49 |
50 | private static void queryMyHomePage(ClassLoader loader)
51 | {
52 | try
53 | {
54 | String s = AntSportsRpcCall.rpcCall_queryMyHomePage(loader);
55 | JSONObject jo = new JSONObject(s);
56 | if(jo.getString("resultCode").equals("SUCCESS"))
57 | {
58 | s = jo.getString("pathJoinStatus");
59 | if(s.equals("GOING"))
60 | {
61 | FriendIdMap.currentUid = jo.getJSONObject("myPositionModel").getString("userId");
62 | String rankCacheKey = jo.getString("rankCacheKey");
63 | JSONArray ja = jo.getJSONArray("treasureBoxModelList");
64 | for(int i = 0; i < ja.length(); i++)
65 | {
66 | parseTreasureBoxModel(loader, ja.getJSONObject(i), rankCacheKey);
67 | }
68 | JSONObject joPathRender = jo.getJSONObject("pathRenderModel");
69 | String title = joPathRender.getString("title");
70 | int minGoStepCount = joPathRender.getInt("minGoStepCount");
71 | jo = jo.getJSONObject("dailyStepModel");
72 | int consumeQuantity = jo.getInt("consumeQuantity");
73 | int produceQuantity = jo.getInt("produceQuantity");
74 | String day = jo.getString("day");
75 | int canMoveStepCount = produceQuantity - consumeQuantity;
76 | if(canMoveStepCount >= minGoStepCount)
77 | {
78 | go(loader, day, rankCacheKey, canMoveStepCount, title);
79 | }
80 | }else if(s.equals("NOT_JOIN"))
81 | {
82 | JSONArray ja = jo.getJSONArray("allPathBaseInfoList");
83 | for(int i = ja.length() - 1; i >= 0; i--)
84 | {
85 | jo = ja.getJSONObject(i);
86 | if(jo.getBoolean("unlocked"))
87 | break;
88 | }
89 | String title = jo.getString("title");
90 | String pathId = jo.getString("pathId");
91 | join(loader, pathId, title);
92 | }
93 | }else
94 | {
95 | Log.i(TAG, jo.getString("resultDesc"));
96 | }
97 | }catch(Throwable t)
98 | {
99 | Log.i(TAG, "queryMyHomePage err:");
100 | Log.printStackTrace(TAG, t);
101 | }
102 | }
103 |
104 | private static void join(ClassLoader loader, String pathId, String title)
105 | {
106 | try
107 | {
108 | String s = AntSportsRpcCall.rpcCall_join(loader, pathId);
109 | JSONObject jo = new JSONObject(s);
110 | if(jo.getString("resultCode").equals("SUCCESS"))
111 | {
112 | Log.other("成功加入〈" + title + "〉路线");
113 | queryMyHomePage(loader);
114 | }else
115 | {
116 | Log.i(TAG, jo.getString("resultDesc"));
117 | }
118 | }catch(Throwable t)
119 | {
120 | Log.i(TAG, "join err:");
121 | Log.printStackTrace(TAG, t);
122 | }
123 | }
124 |
125 | private static void go(ClassLoader loader, String day, String rankCacheKey, int stepCount, String title)
126 | {
127 | try
128 | {
129 | String s = AntSportsRpcCall.rpcCall_go(loader, day, rankCacheKey, stepCount);
130 | JSONObject jo = new JSONObject(s);
131 | if(jo.getString("resultCode").equals("SUCCESS"))
132 | {
133 | Log.other("〈" + title + "〉路线前进了〈" + jo.getInt("goStepCount") + "步〉");
134 | boolean completed = jo.getString("completeStatus").equals("COMPLETED");
135 | JSONArray ja = jo.getJSONArray("allTreasureBoxModelList");
136 | for(int i = 0; i < ja.length(); i++)
137 | {
138 | parseTreasureBoxModel(loader, ja.getJSONObject(i), rankCacheKey);
139 | }
140 | if(completed)
141 | {
142 | Log.other("〈" + title + "〉路线已完成");
143 | queryMyHomePage(loader);
144 | }
145 | }else
146 | {
147 | Log.i(TAG, jo.getString("resultDesc"));
148 | }
149 | }catch(Throwable t)
150 | {
151 | Log.i(TAG, "go err:");
152 | Log.printStackTrace(TAG, t);
153 | }
154 | }
155 |
156 | private static void parseTreasureBoxModel(ClassLoader loader, JSONObject jo, String rankCacheKey)
157 | {
158 | try
159 | {
160 | String canOpenTime = jo.getString("canOpenTime");
161 | String issueTime = jo.getString("issueTime");
162 | String boxNo = jo.getString("boxNo");
163 | String userId = jo.getString("userId");
164 | if(canOpenTime.equals(issueTime))
165 | {
166 | openTreasureBox(loader, boxNo, userId);
167 | }else
168 | {
169 | long cot = Long.parseLong(canOpenTime);
170 | long now = Long.parseLong(rankCacheKey);
171 | long delay = cot - now;
172 | Log.recordLog("还有 " + delay + "ms 才能开宝箱", "");
173 | if(delay < Config.checkInterval())
174 | {
175 | new Thread()
176 | {
177 | long delay;
178 | ClassLoader loader;
179 | String boxNo;
180 | String userId;
181 |
182 | public Thread setData(long l, ClassLoader cl, String bN, String uid)
183 | {
184 | delay = l - 1000;
185 | loader = cl;
186 | boxNo = bN;
187 | userId = uid;
188 | return this;
189 | }
190 |
191 | @Override
192 | public void run()
193 | {
194 | try
195 | {
196 | if(delay > 0) sleep(delay);
197 | Log.recordLog("蹲点开箱开始", "");
198 | long startTime = System.currentTimeMillis();
199 | while(System.currentTimeMillis() - startTime < 5_000)
200 | {
201 | if(openTreasureBox(loader, boxNo, userId) > 0)
202 | break;
203 | sleep(200);
204 | }
205 | }catch(Throwable t)
206 | {
207 | Log.i(TAG, "parseTreasureBoxModel.run err:");
208 | Log.printStackTrace(TAG, t);
209 | }
210 | }
211 |
212 | }.setData(delay, loader, boxNo, userId).start();
213 | }
214 | }
215 | }catch(Throwable t)
216 | {
217 | Log.i(TAG, "parseTreasureBoxModel err:");
218 | Log.printStackTrace(TAG, t);
219 | }
220 | }
221 |
222 | private static int openTreasureBox(ClassLoader loader, String boxNo, String userId)
223 | {
224 | try
225 | {
226 | String s = AntSportsRpcCall.rpcCall_openTreasureBox(loader, boxNo, userId);
227 | JSONObject jo = new JSONObject(s);
228 | if(jo.getString("resultCode").equals("SUCCESS"))
229 | {
230 | JSONArray ja = jo.getJSONArray("treasureBoxAwards");
231 | int num = 0;
232 | for(int i = 0; i < ja.length(); i++)
233 | {
234 | jo = ja.getJSONObject(i);
235 | num += jo.getInt("num");
236 | Log.other("开宝箱获得〈" + num + jo.getString("name") + "〉");
237 | }
238 | return num;
239 | }else
240 | {
241 | Log.recordLog(jo.getString("resultDesc"), "");
242 | }
243 | }catch(Throwable t)
244 | {
245 | Log.i(TAG, "openTreasureBox err:");
246 | Log.printStackTrace(TAG, t);
247 | }
248 | return 0;
249 | }
250 |
251 | private static boolean queryProjectList(ClassLoader loader)
252 | {
253 | boolean haveMore = false;
254 | try
255 | {
256 | String s = AntSportsRpcCall.rpcCall_queryProjectList(loader, 0);
257 | JSONObject jo = new JSONObject(s);
258 | if(jo.getString("resultCode").equals("SUCCESS"))
259 | {
260 | int charityCoinCount = jo.getInt("charityCoinCount");
261 | if(charityCoinCount < 10) return false;
262 | jo = jo.getJSONObject("projectPage");
263 | haveMore = jo.getBoolean("haveMore");
264 | JSONArray ja = jo.getJSONArray("data");
265 | for(int i = 0; i < ja.length(); i++)
266 | {
267 | jo = ja.getJSONObject(i).getJSONObject("basicModel");
268 | if(jo.getString("footballFieldStatus").equals("OPENING_DONATE"))
269 | {
270 | donate(loader, charityCoinCount / 10 * 10, jo.getString("projectId"), jo.getString("title"));
271 | break;
272 | }
273 | }
274 | }else
275 | {
276 | Log.recordLog(TAG, jo.getString("resultDesc"));
277 | }
278 | }catch(Throwable t)
279 | {
280 | Log.i(TAG, "queryProjectList err:");
281 | Log.printStackTrace(TAG, t);
282 | }
283 | return haveMore;
284 | }
285 |
286 | private static void donate(ClassLoader loader, int donateCharityCoin, String projectId, String title)
287 | {
288 | try
289 | {
290 | String s = AntSportsRpcCall.rpcCall_donate(loader, donateCharityCoin, projectId);
291 | JSONObject jo = new JSONObject(s);
292 | if(jo.getString("resultCode").equals("SUCCESS"))
293 | {
294 | Log.other("捐赠〈" + title + "〉〈" + donateCharityCoin + "运动币〉");
295 | }else
296 | {
297 | Log.i(TAG, jo.getString("resultDesc"));
298 | }
299 | }catch(Throwable t)
300 | {
301 | Log.i(TAG, "donate err:");
302 | Log.printStackTrace(TAG, t);
303 | }
304 | }
305 |
306 | private static void queryWalkStep(ClassLoader loader)
307 | {
308 | try
309 | {
310 | String s = AntSportsRpcCall.rpcCall_queryWalkStep(loader);
311 | JSONObject jo = new JSONObject(s);
312 | if(jo.getString("resultCode").equals("SUCCESS"))
313 | {
314 | jo = jo.getJSONObject("dailyStepModel");
315 | int produceQuantity = jo.getInt("produceQuantity");
316 | int hour = Integer.parseInt(Log.getFormatTime().split(":")[0]);
317 | if(produceQuantity >= Config.minExchangeCount() || hour >= Config.latestExchangeTime())
318 | {
319 | s = AntSportsRpcCall.rpcCall_exchange(loader, produceQuantity, 3);
320 | jo = new JSONObject(s);
321 | if(jo.getBoolean("isSuccess"))
322 | {
323 | s = AntSportsRpcCall.rpcCall_exchange_success(loader, jo.getString("exchangeId"));
324 | jo = new JSONObject(s);
325 | if(jo.getBoolean("isSuccess"))
326 | {
327 | int userCount = jo.getInt("userCount");
328 | double amount = jo.getJSONObject("userAmount").getDouble("amount");
329 | Log.other("捐出〈" + userCount + "步〉,兑换〈" + amount + "元〉公益金");
330 | Statistics.exchangeToday();
331 | }else
332 | {
333 | Log.i(TAG, jo.getString("resultDesc"));
334 | }
335 | }else if(s.contains("已捐步"))
336 | {
337 | Statistics.exchangeToday();
338 | }else
339 | {
340 | Log.i(TAG, jo.getString("resultDesc"));
341 | }
342 | }
343 | }else
344 | {
345 | Log.i(TAG, jo.getString("resultDesc"));
346 | }
347 | }catch(Throwable t)
348 | {
349 | Log.i(TAG, "queryWalkStep err:");
350 | Log.printStackTrace(TAG, t);
351 | }
352 | }
353 | }
354 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/KBMember.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy;
2 |
3 | import org.json.JSONObject;
4 | import pansong291.xposed.quickenergy.hook.KBMemberRpcCall;
5 | import pansong291.xposed.quickenergy.util.Config;
6 | import pansong291.xposed.quickenergy.util.Log;
7 | import pansong291.xposed.quickenergy.util.Statistics;
8 |
9 | public class KBMember
10 | {
11 | private static final String TAG = KBMember.class.getCanonicalName();
12 |
13 | public static void start(ClassLoader loader)
14 | {
15 | if(!Config.kbSginIn() || !Statistics.canKbSignInToday())
16 | return;
17 | new Thread()
18 | {
19 | private ClassLoader loader;
20 |
21 | public Thread setData(ClassLoader cl)
22 | {
23 | loader = cl;
24 | return this;
25 | }
26 |
27 | @Override
28 | public void run()
29 | {
30 | try
31 | {
32 | signIn(loader);
33 | }catch(Throwable t)
34 | {
35 | Log.i(TAG, "start.run err:");
36 | Log.printStackTrace(TAG, t);
37 | }
38 | }
39 | }.setData(loader).start();
40 | }
41 |
42 | private static void signIn(ClassLoader loader)
43 | {
44 | try
45 | {
46 | String s = KBMemberRpcCall.rpcCall_signIn(loader);
47 | JSONObject jo = new JSONObject(s);
48 | if(jo.getBoolean("success"))
49 | {
50 | jo = jo.getJSONObject("data");
51 | Log.other("口碑签到〈第" + jo.getString("dayNo") + "天〉,获得〈" + jo.getString("value") + "积分〉");
52 | Statistics.KbSignInToday();
53 | }else if(s.contains("\"HAS_SIGN_IN\""))
54 | {
55 | Statistics.KbSignInToday();
56 | }else
57 | {
58 | Log.i(TAG, jo.getString("errorMessage"));
59 | }
60 | }catch(Throwable t)
61 | {
62 | Log.i(TAG, "signIn err:");
63 | Log.printStackTrace(TAG, t);
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/AntCooperateRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class AntCooperateRpcCall
6 | {
7 | private static final String TAG = AntCooperateRpcCall.class.getCanonicalName();
8 |
9 | public static String rpcCall_queryUserCooperatePlantList(ClassLoader loader)
10 | {
11 | try
12 | {
13 | String args1 = "[{}]";
14 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.queryUserCooperatePlantList", args1);
15 | }catch(Throwable t)
16 | {
17 | Log.i(TAG, "rpcCall_queryUserCooperatePlantList err:");
18 | Log.printStackTrace(TAG, t);
19 | }
20 | return null;
21 | }
22 |
23 | public static String rpcCall_queryCooperatePlant(ClassLoader loader, String coopId)
24 | {
25 | try
26 | {
27 | String args1 = "[{\"cooperationId\":\"" + coopId + "\"}]";
28 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.queryCooperatePlant", args1);
29 | }catch(Throwable t)
30 | {
31 | Log.i(TAG, "rpcCall_queryCooperatePlant err:");
32 | Log.printStackTrace(TAG, t);
33 | }
34 | return null;
35 | }
36 |
37 | public static String rpcCall_cooperateWater(ClassLoader loader, String uid, String coopId, int count)
38 | {
39 | try
40 | {
41 | String args1 = "[{\"bizNo\":\"" + uid + "_" + coopId + "_" + System.currentTimeMillis()
42 | + "\",\"cooperationId\":\"" + coopId + "\",\"energyCount\":" + count + "}]";
43 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.cooperateWater", args1);
44 | }catch(Throwable t)
45 | {
46 | Log.i(TAG, "rpcCall_cooperateWater err:");
47 | Log.printStackTrace(TAG, t);
48 | }
49 | return null;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/AntFarmRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class AntFarmRpcCall
6 | {
7 | private static final String TAG = AntFarmRpcCall.class.getCanonicalName();
8 |
9 | private static final String cityAdCode = "000000",
10 | districtAdCode = "000000", version = "1.0.1910171156.41";
11 |
12 | public static String rpcCall_enterFarm(ClassLoader loader, String farmId, String userId)
13 | {
14 | try
15 | {
16 | String args1 = "[{\"animalId\":\"\",\"cityAdCode\":\"" + cityAdCode + "\",\"districtAdCode\":\"" + districtAdCode + "\",\"farmId\":\"" + farmId +
17 | "\",\"masterFarmId\":\"\",\"recall\":false,\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"touchRecordId\":\"\",\"userId\":\""
18 | + userId + "\",\"version\":\"" + version + "\"}]";
19 | return RpcCall.invoke(loader, "com.alipay.antfarm.enterFarm", args1);
20 | }catch(Throwable t)
21 | {
22 | Log.i(TAG, "rpcCall_enterFarm err:");
23 | Log.printStackTrace(TAG, t);
24 | }
25 | return null;
26 | }
27 |
28 | public static String rpcCall_syncAnimalStatus(ClassLoader loader, String farmId)
29 | {
30 | try
31 | {
32 | String args1 = "[{\"farmId\":\"" + farmId +
33 | "\",\"operType\":\"FEEDSYNC\",\"queryFoodStockInfo\":false,\"recall\":false,\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"userId\":\""
34 | + farmId2UserId(farmId) + "\",\"version\":\"" + version + "\"}]";
35 | return RpcCall.invoke(loader, "com.alipay.antfarm.syncAnimalStatus", args1);
36 | }catch(Throwable t)
37 | {
38 | Log.i(TAG, "rpcCall_syncAnimalStatus err:");
39 | Log.printStackTrace(TAG, t);
40 | }
41 | return null;
42 | }
43 |
44 | public static String rpcCall_rewardFriend(ClassLoader loader, String consistencyKey, String friendId, String productNum, String time)
45 | {
46 | try
47 | {
48 | String args1 = "[{\"canMock\":true,\"consistencyKey\":\"" + consistencyKey
49 | + "\",\"friendId\":\"" + friendId + "\",\"operType\":\"1\",\"productNum\":" + productNum +
50 | ",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"time\":"
51 | + time + ",\"version\":\"" + version + "\"}]";
52 | return RpcCall.invoke(loader, "com.alipay.antfarm.rewardFriend", args1);
53 | }catch(Throwable t)
54 | {
55 | Log.i(TAG, "rpcCall_rewardFriend err:");
56 | Log.printStackTrace(TAG, t);
57 | }
58 | return null;
59 | }
60 |
61 | public static String rpcCall_recallAnimal(ClassLoader loader, String animalId, String currentFarmId, String masterFarmId)
62 | {
63 | try
64 | {
65 | String args1 = "[{\"animalId\":\"" + animalId + "\",\"currentFarmId\":\""
66 | + currentFarmId + "\",\"masterFarmId\":\"" + masterFarmId +
67 | "\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
68 | + version + "\"}]";
69 | return RpcCall.invoke(loader, "com.alipay.antfarm.recallAnimal", args1);
70 | }catch(Throwable t)
71 | {
72 | Log.i(TAG, "rpcCall_recallAnimal err:");
73 | Log.printStackTrace(TAG, t);
74 | }
75 | return null;
76 | }
77 |
78 | public static String rpcCall_sendBackAnimal(ClassLoader loader, String sendType, String animalId, String currentFarmId, String masterFarmId)
79 | {
80 | try
81 | {
82 | String args1 = "[{\"animalId\":\"" + animalId + "\",\"currentFarmId\":\""
83 | + currentFarmId + "\",\"masterFarmId\":\"" + masterFarmId +
84 | "\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"sendType\":\""
85 | + sendType + "\",\"source\":\"H5\",\"version\":\""
86 | + version + "\"}]";
87 | return RpcCall.invoke(loader, "com.alipay.antfarm.sendBackAnimal", args1);
88 | }catch(Throwable t)
89 | {
90 | Log.i(TAG, "rpcCall_sendBackAnimal err:");
91 | Log.printStackTrace(TAG, t);
92 | }
93 | return null;
94 | }
95 |
96 | public static String rpcCall_harvestProduce(ClassLoader loader, String farmId)
97 | {
98 | try
99 | {
100 | String args1 = "[{\"canMock\":true,\"farmId\":\"" + farmId +
101 | "\",\"giftType\":\"\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
102 | + version + "\"}]";
103 | return RpcCall.invoke(loader, "com.alipay.antfarm.harvestProduce", args1);
104 | }catch(Throwable t)
105 | {
106 | Log.i(TAG, "rpcCall_harvestProduce err:");
107 | Log.printStackTrace(TAG, t);
108 | }
109 | return null;
110 | }
111 |
112 | public static String rpcCall_listActivityInfo(ClassLoader loader)
113 | {
114 | try
115 | {
116 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
117 | + version + "\"}]";
118 | return RpcCall.invoke(loader, "com.alipay.antfarm.listActivityInfo", args1);
119 | }catch(Throwable t)
120 | {
121 | Log.i(TAG, "rpcCall_listActivityInfo err:");
122 | Log.printStackTrace(TAG, t);
123 | }
124 | return null;
125 | }
126 |
127 | public static String rpcCall_donation(ClassLoader loader, String activityId)
128 | {
129 | try
130 | {
131 | String args1 = "[{\"activityId\":\"" + activityId +
132 | "\",\"donationAmount\":5,\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
133 | + version + "\"}]";
134 | return RpcCall.invoke(loader, "com.alipay.antfarm.donation", args1);
135 | }catch(Throwable t)
136 | {
137 | Log.i(TAG, "rpcCall_donation err:");
138 | Log.printStackTrace(TAG, t);
139 | }
140 | return null;
141 | }
142 |
143 | public static String rpcCall_listFarmTask(ClassLoader loader)
144 | {
145 | try
146 | {
147 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
148 | + version + "\"}]";
149 | return RpcCall.invoke(loader, "com.alipay.antfarm.listFarmTask", args1);
150 | }catch(Throwable t)
151 | {
152 | Log.i(TAG, "rpcCall_listFarmTask err:");
153 | Log.printStackTrace(TAG, t);
154 | }
155 | return null;
156 | }
157 |
158 | public static String rpcCall_getAnswerInfo(ClassLoader loader)
159 | {
160 | try
161 | {
162 | String args1 = "[{\"answerSource\":\"foodTask\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
163 | + version + "\"}]";
164 | return RpcCall.invoke(loader, "com.alipay.antfarm.getAnswerInfo", args1);
165 | }catch(Throwable t)
166 | {
167 | Log.i(TAG, "rpcCall_getAnswerInfo err:");
168 | Log.printStackTrace(TAG, t);
169 | }
170 | return null;
171 | }
172 |
173 | public static String rpcCall_answerQuestion(ClassLoader loader, String quesId, int answer)
174 | {
175 | try
176 | {
177 | String args1 = "[{\"answers\":\"[{\\\"questionId\\\":\\\"" + quesId + "\\\",\\\"answers\\\":[" + answer +
178 | "]}]\",\"bizkey\":\"ANSWER\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
179 | + version + "\"}]";
180 | return RpcCall.invoke(loader, "com.alipay.antfarm.doFarmTask", args1);
181 | }catch(Throwable t)
182 | {
183 | Log.i(TAG, "rpcCall_answerQuestion err:");
184 | Log.printStackTrace(TAG, t);
185 | }
186 | return null;
187 | }
188 |
189 | public static String rpcCall_receiveFarmTaskAward(ClassLoader loader, String taskId)
190 | {
191 | try
192 | {
193 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"taskId\":\""
194 | + taskId + "\",\"version\":\"" + version + "\"}]";
195 | return RpcCall.invoke(loader, "com.alipay.antfarm.receiveFarmTaskAward", args1);
196 | }catch(Throwable t)
197 | {
198 | Log.i(TAG, "rpcCall_receiveFarmTaskAward err:");
199 | Log.printStackTrace(TAG, t);
200 | }
201 | return null;
202 | }
203 |
204 | public static String rpcCall_listToolTaskDetails(ClassLoader loader)
205 | {
206 | try
207 | {
208 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
209 | + version + "\"}]";
210 | return RpcCall.invoke(loader, "com.alipay.antfarm.listToolTaskDetails", args1);
211 | }catch(Throwable t)
212 | {
213 | Log.i(TAG, "rpcCall_listToolTaskDetails err:");
214 | Log.printStackTrace(TAG, t);
215 | }
216 | return null;
217 | }
218 |
219 | public static String rpcCall_receiveToolTaskReward(ClassLoader loader, String awardType, int rewardCount, String taskType)
220 | {
221 | try
222 | {
223 | String args1 = "[{\"awardType\":\"" + awardType +
224 | "\",\"ignoreLimit\":false,\"requestType\":\"NORMAL\",\"rewardCount\":"
225 | + rewardCount + ",\"rewardType\":\"" + awardType +
226 | "\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"taskType\":\""
227 | + taskType + "\",\"version\":\"" + version + "\"}]";
228 | return RpcCall.invoke(loader, "com.alipay.antfarm.receiveToolTaskReward", args1);
229 | }catch(Throwable t)
230 | {
231 | Log.i(TAG, "rpcCall_receiveToolTaskReward err:");
232 | Log.printStackTrace(TAG, t);
233 | }
234 | return null;
235 | }
236 |
237 | public static String rpcCall_feedAnimal(ClassLoader loader, String farmId)
238 | {
239 | try
240 | {
241 | String args1 = "[{\"animalType\":\"CHICK\",\"canMock\":true,\"farmId\":\"" + farmId +
242 | "\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
243 | + version + "\"}]";
244 | return RpcCall.invoke(loader, "com.alipay.antfarm.feedAnimal", args1);
245 | }catch(Throwable t)
246 | {
247 | Log.i(TAG, "rpcCall_feedAnimal err:");
248 | Log.printStackTrace(TAG, t);
249 | }
250 | return null;
251 | }
252 |
253 | public static String rpcCall_listFarmTool(ClassLoader loader)
254 | {
255 | try
256 | {
257 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
258 | + version + "\"}]";
259 | return RpcCall.invoke(loader, "com.alipay.antfarm.listFarmTool", args1);
260 | }catch(Throwable t)
261 | {
262 | Log.i(TAG, "rpcCall_listFarmTool err:");
263 | Log.printStackTrace(TAG, t);
264 | }
265 | return null;
266 | }
267 |
268 | public static String rpcCall_useFarmTool(ClassLoader loader, String targetFarmId, String toolId, String toolType)
269 | {
270 | try
271 | {
272 | String args1 = "[{\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"targetFarmId\":\""
273 | + targetFarmId + "\",\"toolId\":\"" + toolId + "\",\"toolType\":\"" + toolType + "\",\"version\":\"" + version + "\"}]";
274 | return RpcCall.invoke(loader, "com.alipay.antfarm.useFarmTool", args1);
275 | }catch(Throwable t)
276 | {
277 | Log.i(TAG, "rpcCall_useFarmTool err:");
278 | Log.printStackTrace(TAG, t);
279 | }
280 | return null;
281 | }
282 |
283 | public static String rpcCall_rankingList(ClassLoader loader, int pageStartSum)
284 | {
285 | try
286 | {
287 | String args1 = "[{\"pageSize\":20,\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"startNum\":"
288 | + pageStartSum + ",\"version\":\"" + version + "\"}]";
289 | return RpcCall.invoke(loader, "com.alipay.antfarm.rankingList", args1);
290 | }catch(Throwable t)
291 | {
292 | Log.i(TAG, "rpcCall_rankingList err:");
293 | Log.printStackTrace(TAG, t);
294 | }
295 | return null;
296 | }
297 |
298 | public static String rpcCall_notifyFriend(ClassLoader loader, String animalId, String notifiedFarmId)
299 | {
300 | try
301 | {
302 | String args1 = "[{\"animalId\":\"" + animalId +
303 | "\",\"animalType\":\"CHICK\",\"canBeGuest\":true,\"notifiedFarmId\":\"" + notifiedFarmId +
304 | "\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
305 | + version + "\"}]";
306 | return RpcCall.invoke(loader, "com.alipay.antfarm.notifyFriend", args1);
307 | }catch(Throwable t)
308 | {
309 | Log.i(TAG, "rpcCall_notifyFriend err:");
310 | Log.printStackTrace(TAG, t);
311 | }
312 | return null;
313 | }
314 |
315 | public static String rpcCall_feedFriendAnimal(ClassLoader loader, String friendFarmId)
316 | {
317 | try
318 | {
319 | String args1 = "[{\"animalType\":\"CHICK\",\"canMock\":true,\"friendFarmId\":\"" + friendFarmId +
320 | "\",\"requestType\":\"NORMAL\",\"sceneCode\":\"ANTFARM\",\"source\":\"H5\",\"version\":\""
321 | + version + "\"}]";
322 | return RpcCall.invoke(loader, "com.alipay.antfarm.feedFriendAnimal", args1);
323 | }catch(Throwable t)
324 | {
325 | Log.i(TAG, "rpcCall_feedFriendAnimal err:");
326 | Log.printStackTrace(TAG, t);
327 | }
328 | return null;
329 | }
330 |
331 | public static String farmId2UserId(String farmId)
332 | {
333 | int l = farmId.length() / 2;
334 | return farmId.substring(l);
335 | }
336 |
337 | }
338 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/AntForestRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class AntForestRpcCall
6 | {
7 | private static final String TAG = AntForestRpcCall.class.getCanonicalName();
8 |
9 | public static String rpcCall_queryEnergyRanking(ClassLoader loader, String startPoint)
10 | {
11 | try
12 | {
13 | String args1 = "[{\"av\":\"5\",\"ct\":\"android\",\"pageSize\":20,\"startPoint\":\""
14 | + startPoint + "\"}]";
15 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.queryEnergyRanking", args1);
16 | }catch(Throwable t)
17 | {
18 | Log.i(TAG, "rpcCall_queryEnergyRanking err:");
19 | Log.printStackTrace(TAG, t);
20 | }
21 | return null;
22 | }
23 |
24 | public static String rpcCall_queryNextAction(ClassLoader loader, String userId)
25 | {
26 | try
27 | {
28 | String args1 = "[{\"canRobFlags\":\"F,F,F\",\"source\":\"_NO_SOURCE_\",\"userId\":\""
29 | + userId + "\",\"version\":\"20181220\"}]";
30 | String res = RpcCall.invoke(loader, "alipay.antmember.forest.h5.queryNextAction", args1);
31 |
32 | // args1 = "[{\"av\":\"5\",\"ct\":\"android\",\"pageSize\":3,\"startIndex\":0,\"userId\":\""
33 | // + userId + "\"}]";
34 | // RpcCall.invoke(loader, "alipay.antmember.forest.h5.pageQueryDynamics", args1);
35 |
36 | return res;
37 | }catch(Throwable t)
38 | {
39 | Log.i(TAG, "rpcCall_queryNextAction err:");
40 | Log.printStackTrace(TAG, t);
41 | }
42 | return null;
43 | }
44 |
45 | public static String rpcCall_collectEnergy(ClassLoader loader, String userId, long bubbleId)
46 | {
47 | try
48 | {
49 | String args1 = "[{\"bubbleIds\":[" + bubbleId + "],\"userId\":\"" + userId + "\"}]";
50 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.collectEnergy", args1);
51 | }catch(Throwable t)
52 | {
53 | Log.i(TAG, "rpcCall_collectEnergy err:");
54 | Log.printStackTrace(TAG, t);
55 | }
56 | return null;
57 | }
58 |
59 | public static String rpcCall_transferEnergy(ClassLoader loader, String targetUser, String bizNo, int ordinal)
60 | {
61 | try
62 | {
63 | String args1 = "[{\"bizNo\":\"" + bizNo + ordinal + "\",\"targetUser\":\""
64 | + targetUser + "\",\"transferType\":\"WATERING\",\"version\":\"20181217\"}]";//
65 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.transferEnergy", args1);
66 | }catch(Throwable t)
67 | {
68 | Log.i(TAG, "rpcCall_transferEnergy err:");
69 | Log.printStackTrace(TAG, t);
70 | }
71 | return null;
72 | }
73 |
74 | public static String rpcCall_forFriendCollectEnergy(ClassLoader loader, String targetUserId, long bubbleId)
75 | {
76 | try
77 | {
78 | String args1 = "[{\"bubbleIds\":[" + bubbleId + "],\"targetUserId\":\"" + targetUserId + "\"}]";
79 | return RpcCall.invoke(loader, "alipay.antmember.forest.h5.forFriendCollectEnergy", args1);
80 | }catch(Throwable t)
81 | {
82 | Log.i(TAG, "rpcCall_forFriendCollectEnergy err:");
83 | Log.printStackTrace(TAG, t);
84 | }
85 | return null;
86 | }
87 |
88 | public static String rpcCall_queryTaskList(ClassLoader loader)
89 | {
90 | try
91 | {
92 | String args1 = "[{\"version\":\"20191010\"}]"; //
93 | return RpcCall.invoke(loader, "alipay.antforest.forest.h5.queryTaskList", args1);
94 | }catch(Throwable t)
95 | {
96 | Log.i(TAG, "rpcCall_queryTaskList err:");
97 | Log.printStackTrace(TAG, t);
98 | }
99 | return null;
100 | }
101 |
102 | public static String rpcCall_receiveTaskAward(ClassLoader loader, String taskType)
103 | {
104 | try
105 | {
106 | String args1 =
107 | "[{\"ignoreLimit\":false,\"requestType\":\"H5\",\"sceneCode\":\"ANTFOREST_TASK\",\"source\":\"ANTFOREST\",\"taskType\":\""
108 | + taskType + "\"}]";
109 | return RpcCall.invoke(loader, "com.alipay.antiep.receiveTaskAward", args1);
110 | }catch(Throwable t)
111 | {
112 | Log.i(TAG, "rpcCall_receiveTaskAward err:");
113 | Log.printStackTrace(TAG, t);
114 | }
115 | return null;
116 | }
117 |
118 | private static String rpcCall_queryPropList(ClassLoader loader)
119 | {
120 | try
121 | {
122 | String args1 = "[{\"version\":\"\"}]"; //20181217
123 | return RpcCall.invoke(loader, "alipay.antforest.forest.h5.queryPropList", args1);
124 | }catch(Throwable t)
125 | {
126 | Log.i(TAG, "rpcCall_queryPropList err:");
127 | Log.printStackTrace(TAG, t);
128 | }
129 | return null;
130 | }
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/AntMemberRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class AntMemberRpcCall
6 | {
7 | private static final String TAG = AntMemberRpcCall.class.getCanonicalName();
8 |
9 | private static final String appVersion = "3.0.0";
10 |
11 | /* ant member point */
12 | public static String rpcCall_queryPointCert(ClassLoader loader, int page, int pageSize)
13 | {
14 | try
15 | {
16 | String args1 = "[{\"page\":" + page + ",\"pageSize\":" + pageSize + "}]";
17 | return RpcCall.invoke(loader, "alipay.antmember.biz.rpc.member.h5.queryPointCert", args1);
18 | }catch(Throwable t)
19 | {
20 | Log.i(TAG, "rpcCall_queryPointCert err:");
21 | Log.printStackTrace(TAG, t);
22 | }
23 | return null;
24 | }
25 |
26 | public static String rpcCall_receivePointByUser(ClassLoader loader, String certId)
27 | {
28 | try
29 | {
30 | String args1 = "[{\"certId\":" + certId + "}]";
31 | return RpcCall.invoke(loader, "alipay.antmember.biz.rpc.member.h5.receivePointByUser", args1);
32 | }catch(Throwable t)
33 | {
34 | Log.i(TAG, "rpcCall_receivePointByUser err:");
35 | Log.printStackTrace(TAG, t);
36 | }
37 | return null;
38 | }
39 |
40 | public static String rpcCall_queryPoint(ClassLoader loader)
41 | {
42 | try
43 | {
44 | String args1 = "[{}]";
45 | return RpcCall.invoke(loader, "alipay.antmember.h5.queryPoint", args1);
46 | }catch(Throwable t)
47 | {
48 | Log.i(TAG, "rpcCall_queryPoint err:");
49 | Log.printStackTrace(TAG, t);
50 | }
51 | return null;
52 | }
53 |
54 | public static String rpcCall_memberSignin(ClassLoader loader)
55 | {
56 | try
57 | {
58 | String args1 = "[{}]";
59 | return RpcCall.invoke(loader, "alipay.antmember.biz.rpc.member.h5.memberSignin", args1);
60 | }catch(Throwable t)
61 | {
62 | Log.i(TAG, "rpcCall_memberSignin err:");
63 | Log.printStackTrace(TAG, t);
64 | }
65 | return null;
66 | }
67 |
68 | /* family point*/
69 | public static String rpcCall_familySignin(ClassLoader loader)
70 | {
71 | try
72 | {
73 | String args1 = "[{\"appVersion\": \"" + appVersion +
74 | "\",\"clientTraceId\": \"\",\"source\": \"JTHYJGW\"}]";
75 | return RpcCall.invoke(loader, "alipay.peerpayprod.family.signin", args1);
76 | }catch(Throwable t)
77 | {
78 | Log.i(TAG, "rpcCall_familySignin err:");
79 | Log.printStackTrace(TAG, t);
80 | }
81 | return null;
82 | }
83 |
84 | public static String rpcCall_familyHomepage(ClassLoader loader)
85 | {
86 | try
87 | {
88 | String args1 = "[{\"appVersion\": \"" + appVersion +
89 | "\",\"clientTraceId\": \"\",\"source\": \"JTHYJGW\"}]";
90 | return RpcCall.invoke(loader, "alipay.peerpayprod.family.homepage", args1);
91 | }catch(Throwable t)
92 | {
93 | Log.i(TAG, "rpcCall_familyHomepage err:");
94 | Log.printStackTrace(TAG, t);
95 | }
96 | return null;
97 | }
98 |
99 | public static String rpcCall_queryFamilyPointCert(ClassLoader loader, String familyId)
100 | {
101 | try
102 | {
103 | String args1 = "[{\"familyId\":\"" + familyId +
104 | "\",\"limit\":20,\"needQueryOtherMemberCert\":false}]";
105 | return RpcCall.invoke(loader, "com.alipay.alipaymember.biz.rpc.family.h5.queryFamilyPointCert", args1);
106 | }catch(Throwable t)
107 | {
108 | Log.i(TAG, "rpcCall_queryFamilyPointCert err:");
109 | Log.printStackTrace(TAG, t);
110 | }
111 | return null;
112 | }
113 |
114 | public static String rpcCall_claimFamilyPointCert(ClassLoader loader, long certId, String familyId)
115 | {
116 | try
117 | {
118 | String args1 = "[{\"certId\":" + certId + ",\"familyId\":\""
119 | + familyId + "\"}]";
120 | return RpcCall.invoke(loader, "com.alipay.alipaymember.biz.rpc.family.h5.claimFamilyPointCert", args1);
121 | }catch(Throwable t)
122 | {
123 | Log.i(TAG, "rpcCall_claimFamilyPointCert err:");
124 | Log.printStackTrace(TAG, t);
125 | }
126 | return null;
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/AntSportsRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class AntSportsRpcCall
6 | {
7 | private static final String TAG = AntSportsRpcCall.class.getCanonicalName();
8 | private static final String chInfo = "antsports-account",
9 | timeZone = "Asia\\/Shanghai", version = "3.0.1.2";
10 |
11 | public static String rpcCall_queryMyHomePage(ClassLoader loader)
12 | {
13 | try
14 | {
15 | String args1 = "[{\"chInfo\":\"" + chInfo
16 | + "\",\"pathListUsePage\":true,\"timeZone\":\"" + timeZone + "\"}]";
17 | return RpcCall.invoke(loader, "alipay.antsports.walk.map.queryMyHomePage", args1);
18 | }catch(Throwable t)
19 | {
20 | Log.i(TAG, "rpcCall_queryMyHomePage err:");
21 | Log.printStackTrace(TAG, t);
22 | }
23 | return null;
24 | }
25 |
26 | public static String rpcCall_join(ClassLoader loader, String pathId)
27 | {
28 | try
29 | {
30 | String args1 = "[{\"chInfo\":\"" + chInfo
31 | + "\",\"pathId\":\"" + pathId + "\"}]";
32 | return RpcCall.invoke(loader, "alipay.antsports.walk.map.join", args1);
33 | }catch(Throwable t)
34 | {
35 | Log.i(TAG, "rpcCall_join err:");
36 | Log.printStackTrace(TAG, t);
37 | }
38 | return null;
39 | }
40 |
41 | public static String rpcCall_go(ClassLoader loader, String day, String rankCacheKey, int stepCount)
42 | {
43 | try
44 | {
45 | String args1 = "[{\"chInfo\":\"" + chInfo + "\",\"day\":\"" + day
46 | + "\",\"needAllBox\":true,\"rankCacheKey\":\"" + rankCacheKey
47 | + "\",\"timeZone\":\"" + timeZone + "\",\"useStepCount\":" + stepCount + "}]";
48 | return RpcCall.invoke(loader, "alipay.antsports.walk.map.go", args1);
49 | }catch(Throwable t)
50 | {
51 | Log.i(TAG, "rpcCall_go err:");
52 | Log.printStackTrace(TAG, t);
53 | }
54 | return null;
55 | }
56 |
57 | public static String rpcCall_openTreasureBox(ClassLoader loader, String boxNo, String userId)
58 | {
59 | try
60 | {
61 | String args1 = "[{\"boxNo\":\"" + boxNo + "\",\"chInfo\":\""
62 | + chInfo + "\",\"userId\":\"" + userId + "\"}]";
63 | return RpcCall.invoke(loader, "alipay.antsports.walk.treasureBox.openTreasureBox", args1);
64 | }catch(Throwable t)
65 | {
66 | Log.i(TAG, "rpcCall_openTreasureBox err:");
67 | Log.printStackTrace(TAG, t);
68 | }
69 | return null;
70 | }
71 |
72 | public static String rpcCall_queryProjectList(ClassLoader loader, int index)
73 | {
74 | try
75 | {
76 | String args1 = "[{\"chInfo\":\"" + chInfo + "\",\"index\":"
77 | + index + ",\"projectListUseVertical\":true}]";
78 | return RpcCall.invoke(loader, "alipay.antsports.walk.charity.queryProjectList", args1);
79 | }catch(Throwable t)
80 | {
81 | Log.i(TAG, "rpcCall_queryProjectList err:");
82 | Log.printStackTrace(TAG, t);
83 | }
84 | return null;
85 | }
86 |
87 | public static String rpcCall_donate(ClassLoader loader, int donateCharityCoin, String projectId)
88 | {
89 | try
90 | {
91 | String args1 = "[{\"chInfo\":\"" + chInfo + "\",\"donateCharityCoin\":"
92 | + donateCharityCoin + ",\"projectId\":\"" + projectId + "\"}]";
93 | return RpcCall.invoke(loader, "alipay.antsports.walk.charity.donate", args1);
94 | }catch(Throwable t)
95 | {
96 | Log.i(TAG, "rpcCall_queryProjectList err:");
97 | Log.printStackTrace(TAG, t);
98 | }
99 | return null;
100 | }
101 |
102 | public static String rpcCall_queryWalkStep(ClassLoader loader)
103 | {
104 | try
105 | {
106 | String args1 = "[{\"timeZone\":\"" + timeZone + "\"}]";
107 | return RpcCall.invoke(loader, "alipay.antsports.walk.user.queryWalkStep", args1);
108 | }catch(Throwable t)
109 | {
110 | Log.i(TAG, "rpcCall_queryWalkStep err:");
111 | Log.printStackTrace(TAG, t);
112 | }
113 | return null;
114 | }
115 |
116 | public static String rpcCall_exchange(ClassLoader loader, int count, int ver)
117 | {
118 | try
119 | {
120 | String args1 = "[{\"actId\":\"\",\"count\":" + count
121 | + ",\"timezone\":\"" + timeZone + "\",\"ver\":"
122 | + ver + ",\"version\":\"" + version + "\"}]";
123 | return RpcCall.invoke(loader, "alipay.charity.mobile.donate.exchange", args1);
124 | }catch(Throwable t)
125 | {
126 | Log.i(TAG, "rpcCall_exchange err:");
127 | Log.printStackTrace(TAG, t);
128 | }
129 | return null;
130 | }
131 |
132 | public static String rpcCall_exchange_success(ClassLoader loader, String exchangeId)
133 | {
134 | try
135 | {
136 | String args1 = "[{\"exchangeId\":\"" + exchangeId
137 | + "\",\"timezone\":\"GMT+08:00\",\"version\":\"" + version + "\"}]";
138 | return RpcCall.invoke(loader, "alipay.charity.mobile.donate.exchange.success", args1);
139 | }catch(Throwable t)
140 | {
141 | Log.i(TAG, "rpcCall_exchange_success err:");
142 | Log.printStackTrace(TAG, t);
143 | }
144 | return null;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/ClassMember.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | public class ClassMember
4 | {
5 | public static final String
6 | com_eg_android_AlipayGphone = "com.eg.android.AlipayGphone",
7 | com_eg_android_AlipayGphone_AlipayLogin = "com.eg.android.AlipayGphone.AlipayLogin",
8 | com_alipay_android_launcher_service_LauncherService = "com.alipay.android.launcher.service.LauncherService",
9 | com_alipay_mobile_nebulaappproxy_api_rpc_H5AppRpcUpdate = "com.alipay.mobile.nebulaappproxy.api.rpc.H5AppRpcUpdate",
10 | matchVersion = "matchVersion",
11 | a = "a", h = "h",
12 | com_alipay_mobile_h5container_api_H5Page = "com.alipay.mobile.h5container.api.H5Page",
13 | com_alibaba_fastjson_JSONObject = "com.alibaba.fastjson.JSONObject",
14 | com_alipay_mobile_nebulaappproxy_api_rpc_H5RpcUtil = "com.alipay.mobile.nebulaappproxy.api.rpc.H5RpcUtil",
15 | rpcCall = "rpcCall",
16 | com_alipay_mobile_nebulacore_ui_H5FragmentManager = "com.alipay.mobile.nebulacore.ui.H5FragmentManager",
17 | com_alipay_mobile_nebulacore_ui_H5Fragment = "com.alipay.mobile.nebulacore.ui.H5Fragment",
18 | pushFragment = "pushFragment",
19 | com_alipay_mobile_nebulacore_ui_H5Activity = "com.alipay.mobile.nebulacore.ui.H5Activity",
20 | onCreate = "onCreate", onResume = "onResume", onDestroy = "onDestroy",
21 | getResponse = "getResponse";
22 |
23 | public static final String
24 | com_alipay_mobile_nebulabiz_rpc_H5RpcUtil = "com.alipay.mobile.nebulabiz.rpc.H5RpcUtil";
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/KBMemberRpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import pansong291.xposed.quickenergy.util.Log;
4 |
5 | public class KBMemberRpcCall
6 | {
7 | private static final String TAG = KBMemberRpcCall.class.getCanonicalName();
8 | private static final String version = "2.0";
9 |
10 | public static String rpcCall_signIn(ClassLoader loader)
11 | {
12 | try
13 | {
14 | String args1 = "[{\"sceneCode\":\"KOUBEI_INTEGRAL\",\"source\":\"ALIPAY_TAB\",\"version\":\"" + version + "\"}]";
15 | return RpcCall.invoke(loader, "alipay.kbmemberprod.action.signIn", args1);
16 | }catch(Throwable t)
17 | {
18 | Log.i(TAG, "rpcCall_signIn err:");
19 | Log.printStackTrace(TAG, t);
20 | }
21 | return null;
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/RpcCall.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import android.content.Intent;
4 | import java.lang.reflect.InvocationTargetException;
5 | import java.lang.reflect.Method;
6 | import pansong291.xposed.quickenergy.AntForestToast;
7 | import pansong291.xposed.quickenergy.util.Config;
8 | import pansong291.xposed.quickenergy.util.Log;
9 |
10 | public class RpcCall
11 | {
12 | private static final String TAG = RpcCall.class.getCanonicalName();
13 | private static Method rpcCallMethod;
14 | private static Method getResponseMethod;
15 | private static Object curH5PageImpl;
16 | public static boolean sendXEdgeProBroadcast;
17 |
18 | public static String invoke(ClassLoader loader, String args0, String args1)
19 | {
20 | if(rpcCallMethod == null)
21 | {
22 | try
23 | {
24 | Class> rpcClazz = loader.loadClass(ClassMember.com_alipay_mobile_nebulabiz_rpc_H5RpcUtil);
25 | Class> h5PageClazz = loader.loadClass(ClassMember.com_alipay_mobile_h5container_api_H5Page);
26 | Class> jsonClazz = loader.loadClass(ClassMember.com_alibaba_fastjson_JSONObject);
27 | rpcCallMethod = rpcClazz.getMethod(
28 | ClassMember.rpcCall, String.class, String.class, String.class,
29 | boolean.class, jsonClazz, String.class, boolean.class, h5PageClazz,
30 | int.class, String.class, boolean.class, int.class);
31 | Log.i(TAG, "get Old RpcCallMethod successfully");
32 | }catch(Throwable t)
33 | {
34 | Log.i(TAG, "get Old RpcCallMethod err:");
35 | //Log.printStackTrace(TAG, t);
36 | }
37 |
38 | if(rpcCallMethod == null)
39 | try
40 | {
41 | Class> h5PageClazz = loader.loadClass(ClassMember.com_alipay_mobile_h5container_api_H5Page);
42 | Class> jsonClazz = loader.loadClass(ClassMember.com_alibaba_fastjson_JSONObject);
43 | Class> rpcClazz = loader.loadClass(ClassMember.com_alipay_mobile_nebulaappproxy_api_rpc_H5RpcUtil);
44 | rpcCallMethod = rpcClazz.getMethod(
45 | ClassMember.rpcCall, String.class, String.class, String.class,
46 | boolean.class, jsonClazz, String.class, boolean.class, h5PageClazz,
47 | int.class, String.class, boolean.class, int.class, String.class);
48 | Log.i(TAG, "get RpcCallMethod successfully");
49 | }catch(Throwable t)
50 | {
51 | Log.i(TAG, "get RpcCallMethod err:");
52 | //Log.printStackTrace(TAG, t);
53 | }
54 | }
55 |
56 | try
57 | {
58 | Object o = null;
59 | switch(rpcCallMethod.getParameterTypes().length)
60 | {
61 | case 12:
62 | o = rpcCallMethod.invoke(
63 | null, args0, args1, "", true, null, null, false, curH5PageImpl, 0, "", false, -1);
64 | break;
65 | default:
66 | o = rpcCallMethod.invoke(
67 | null, args0, args1, "", true, null, null, false, curH5PageImpl, 0, "", false, -1, "");
68 | }
69 | String str = getResponse(o);
70 | Log.i(TAG, "argument: " + args0 + ", " + args1);
71 | Log.i(TAG, "response: " + str);
72 | return str;
73 | }catch(Throwable t)
74 | {
75 | Log.i(TAG, "invoke err:");
76 | Log.printStackTrace(TAG, t);
77 | if(t instanceof InvocationTargetException)
78 | {
79 | if(AntForestToast.context != null && sendXEdgeProBroadcast)
80 | {
81 | sendXEdgeProBroadcast = false;
82 | Intent it = new Intent("com.jozein.xedgepro.PERFORM");
83 | it.putExtra("data", Config.xedgeproData());
84 | AntForestToast.context.sendBroadcast(it);
85 | Log.recordLog(t.getCause().getMessage() + ",发送XposedEdgePro广播", "");
86 | }
87 | }
88 | }
89 | return null;
90 | }
91 |
92 | public static String getResponse(Object resp)
93 | {
94 | try
95 | {
96 | if(getResponseMethod == null)
97 | getResponseMethod = resp.getClass().getMethod(ClassMember.getResponse);
98 |
99 | return (String) getResponseMethod.invoke(resp);
100 | }catch(Throwable t)
101 | {
102 | Log.i(TAG, "getResponse err:");
103 | Log.printStackTrace(TAG, t);
104 | }
105 | return null;
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/hook/XposedHook.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.hook;
2 |
3 | import android.app.AlarmManager;
4 | import android.app.PendingIntent;
5 | import android.app.Service;
6 | import android.content.Intent;
7 | import android.os.Handler;
8 | import android.os.PowerManager;
9 | import de.robv.android.xposed.IXposedHookLoadPackage;
10 | import de.robv.android.xposed.XC_MethodHook;
11 | import de.robv.android.xposed.XC_MethodReplacement;
12 | import de.robv.android.xposed.XposedHelpers;
13 | import de.robv.android.xposed.callbacks.XC_LoadPackage;
14 | import java.util.Map;
15 | import pansong291.xposed.quickenergy.AntCooperate;
16 | import pansong291.xposed.quickenergy.AntFarm;
17 | import pansong291.xposed.quickenergy.AntForest;
18 | import pansong291.xposed.quickenergy.AntForestNotification;
19 | import pansong291.xposed.quickenergy.AntForestToast;
20 | import pansong291.xposed.quickenergy.AntMember;
21 | import pansong291.xposed.quickenergy.AntSports;
22 | import pansong291.xposed.quickenergy.KBMember;
23 | import pansong291.xposed.quickenergy.ui.MainActivity;
24 | import pansong291.xposed.quickenergy.util.Config;
25 | import pansong291.xposed.quickenergy.util.Log;
26 | import pansong291.xposed.quickenergy.util.Statistics;
27 |
28 | public class XposedHook implements IXposedHookLoadPackage
29 | {
30 | private static final String TAG = XposedHook.class.getCanonicalName();
31 | private static PowerManager.WakeLock wakeLock;
32 | public static Handler handler;
33 | private static Runnable runnable;
34 | private static int times;
35 |
36 | @Override
37 | public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable
38 | {
39 | if("pansong291.xposed.quickenergy".equals(lpparam.packageName))
40 | {
41 | XposedHelpers.findAndHookMethod(MainActivity.class.getName(), lpparam.classLoader, "setModuleActive", boolean.class, new XC_MethodHook()
42 | {
43 | @Override
44 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable
45 | {
46 | param.args[0] = true;
47 | }
48 | });
49 | }
50 |
51 | if(ClassMember.com_eg_android_AlipayGphone.equals(lpparam.packageName))
52 | {
53 | Log.i(TAG, lpparam.packageName);
54 | hookLauncherService(lpparam.classLoader);
55 | hookRpcCall(lpparam.classLoader);
56 | }
57 | }
58 |
59 | private void hookLauncherService(ClassLoader loader)
60 | {
61 | try
62 | {
63 | XposedHelpers.findAndHookMethod(
64 | ClassMember.com_alipay_android_launcher_service_LauncherService, loader, ClassMember.onCreate, new XC_MethodHook()
65 | {
66 | ClassLoader loader;
67 |
68 | public XC_MethodHook setData(ClassLoader cl)
69 | {
70 | loader = cl;
71 | return this;
72 | }
73 |
74 | @Override
75 | protected void afterHookedMethod(MethodHookParam param) throws Throwable
76 | {
77 | Service service = (Service) param.thisObject;
78 | AntForestToast.context = service.getApplicationContext();
79 | times = 0;
80 | if(Config.stayAwake())
81 | {
82 | PowerManager pm = (PowerManager) service.getSystemService(service.POWER_SERVICE);
83 | wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, service.getClass().getName());
84 | wakeLock.acquire();
85 | }
86 | if(handler == null) handler = new Handler();
87 | if(runnable == null) runnable = new Runnable()
88 | {
89 | Service service;
90 | ClassLoader loader;
91 |
92 | public Runnable setData(Service s, ClassLoader cl)
93 | {
94 | service = s;
95 | loader = cl;
96 | return this;
97 | }
98 |
99 | @Override
100 | public void run()
101 | {
102 | Config.shouldReload = true;
103 | RpcCall.sendXEdgeProBroadcast = true;
104 | Statistics.resetToday();
105 | AntForest.checkEnergyRanking(loader, times);
106 | AntCooperate.start(loader, times);
107 | AntFarm.start(loader);
108 | AntMember.receivePoint(loader, times);
109 | AntSports.start(loader, times);
110 | KBMember.start(loader);
111 | if(Config.collectEnergy() || Config.enableFarm())
112 | handler.postDelayed(this, Config.checkInterval());
113 | else AntForestNotification.stop(service, false);
114 | times = (times + 1) % (3600_000 / Config.checkInterval());
115 | }
116 | }.setData(service, loader);
117 | if(Config.collectEnergy() || Config.enableFarm())
118 | {
119 | AntForestNotification.start(service);
120 | handler.post(runnable);
121 | }
122 | }
123 | }.setData(loader));
124 | Log.i(TAG, "hook " + ClassMember.onCreate + " successfully");
125 | }catch(Throwable t)
126 | {
127 | Log.i(TAG, "hook " + ClassMember.onCreate + " err:");
128 | Log.printStackTrace(TAG, t);
129 | }
130 |
131 | try
132 | {
133 | XposedHelpers.findAndHookMethod(ClassMember.com_alipay_android_launcher_service_LauncherService, loader, ClassMember.onDestroy, new XC_MethodHook()
134 | {
135 | @Override
136 | protected void afterHookedMethod(MethodHookParam param) throws Throwable
137 | {
138 | if(wakeLock != null)
139 | {
140 | wakeLock.release();
141 | wakeLock = null;
142 | }
143 | Service service = (Service) param.thisObject;
144 | AntForestNotification.stop(service, false);
145 | AntForestNotification.setContentText("支付宝前台服务被销毁");
146 | Log.recordLog("支付宝前台服务被销毁", "");
147 | handler.removeCallbacks(runnable);
148 | if(Config.autoRestart())
149 | {
150 | AlarmManager alarmManager = (AlarmManager) service.getSystemService(service.ALARM_SERVICE);
151 | Intent it = new Intent();
152 | it.setClassName(ClassMember.com_eg_android_AlipayGphone, ClassMember.com_alipay_android_launcher_service_LauncherService);
153 | PendingIntent pi = PendingIntent.getService(service, 0, it, PendingIntent.FLAG_UPDATE_CURRENT);
154 | alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 1000, pi);
155 | }
156 | }
157 | });
158 | Log.i(TAG, "hook " + ClassMember.onDestroy + " successfully");
159 | }catch(Throwable t)
160 | {
161 | Log.i(TAG, "hook " + ClassMember.onDestroy + " err:");
162 | Log.printStackTrace(TAG, t);
163 | }
164 | }
165 |
166 | private void hookRpcCall(ClassLoader loader)
167 | {
168 | try
169 | {
170 | Class> clazz = loader.loadClass(ClassMember.com_alipay_mobile_nebulaappproxy_api_rpc_H5AppRpcUpdate);
171 | Class> H5PageClazz = loader.loadClass(ClassMember.com_alipay_mobile_h5container_api_H5Page);
172 | XposedHelpers.findAndHookMethod(
173 | clazz, ClassMember.matchVersion, H5PageClazz, Map.class, String.class,
174 | XC_MethodReplacement.returnConstant(false));
175 | Log.i(TAG, "hook " + ClassMember.matchVersion + " successfully");
176 | }catch(Throwable t)
177 | {
178 | Log.i(TAG, "hook " + ClassMember.matchVersion + " err:");
179 | Log.printStackTrace(TAG, t);
180 | }
181 |
182 | }
183 |
184 |
185 | }
186 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/AlipayCooperate.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import pansong291.xposed.quickenergy.util.CooperationIdMap;
8 |
9 | public class AlipayCooperate extends AlipayId
10 | {
11 | private static List list;
12 |
13 | public AlipayCooperate(String i, String n)
14 | {
15 | id = i;
16 | name = n;
17 | }
18 |
19 | public static List getList()
20 | {
21 | if(list == null || CooperationIdMap.shouldReload)
22 | {
23 | list = new ArrayList();
24 | Set idSet = CooperationIdMap.getIdMap().entrySet();
25 | for(Map.Entry entry: idSet)
26 | {
27 | list.add(new AlipayCooperate(entry.getKey().toString(), entry.getValue().toString()));
28 | }
29 | }
30 | return list;
31 | }
32 |
33 | public static void remove(String id)
34 | {
35 | getList();
36 | for(int i = 0; i < list.size(); i++)
37 | {
38 | if(list.get(i).id.equals(id))
39 | {
40 | list.remove(i);
41 | break;
42 | }
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/AlipayId.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | public class AlipayId
4 | {
5 | public String name;
6 | public String id;
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/AlipayUser.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import pansong291.xposed.quickenergy.util.FriendIdMap;
8 |
9 | public class AlipayUser extends AlipayId
10 | {
11 | private static List list;
12 |
13 | public AlipayUser(String i, String n)
14 | {
15 | id = i;
16 | name = n;
17 | }
18 |
19 | public static List getList()
20 | {
21 | if(list == null || FriendIdMap.shouldReload)
22 | {
23 | list = new ArrayList();
24 | Set idSet = FriendIdMap.getIdMap().entrySet();
25 | for(Map.Entry entry: idSet)
26 | {
27 | list.add(new AlipayUser(entry.getKey().toString(), entry.getValue().toString()));
28 | }
29 | }
30 | return list;
31 | }
32 |
33 | public static void remove(String id)
34 | {
35 | getList();
36 | for(int i = 0; i < list.size(); i++)
37 | {
38 | if(list.get(i).id.equals(id))
39 | {
40 | list.remove(i);
41 | break;
42 | }
43 | }
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/ChoiceDialog.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.DialogInterface.OnClickListener;
7 | import pansong291.xposed.quickenergy.AntFarm.SendType;
8 | import pansong291.xposed.quickenergy.util.Config;
9 | import pansong291.xposed.quickenergy.util.Config.RecallAnimalType;
10 |
11 | public class ChoiceDialog
12 | {
13 | private static AlertDialog
14 | sendTypeDialog, recallAnimalTypeDialog;
15 |
16 | public static void showSendType(Context c, CharSequence title)
17 | {
18 | try
19 | {
20 | getSendTypeDialog(c, title).show();
21 | }catch(Throwable t)
22 | {
23 | sendTypeDialog = null;
24 | getSendTypeDialog(c, title).show();
25 | }
26 | }
27 |
28 | private static AlertDialog getSendTypeDialog(Context c, CharSequence title)
29 | {
30 | if(sendTypeDialog == null)
31 | sendTypeDialog = new AlertDialog.Builder(c)
32 | .setTitle(title)
33 | .setSingleChoiceItems(SendType.names, Config.sendType().ordinal(),
34 | new OnClickListener()
35 | {
36 | @Override
37 | public void onClick(DialogInterface p1, int p2)
38 | {
39 | Config.setSendType(p2);
40 | }
41 | })
42 | .setPositiveButton("OK", null)
43 | .create();
44 | return sendTypeDialog;
45 | }
46 |
47 | public static void showRecallAnimalType(Context c, CharSequence title)
48 | {
49 | try
50 | {
51 | getRecallAnimalTypeDialog(c, title).show();
52 | }catch(Throwable t)
53 | {
54 | recallAnimalTypeDialog = null;
55 | getRecallAnimalTypeDialog(c, title).show();
56 | }
57 | }
58 |
59 | private static AlertDialog getRecallAnimalTypeDialog(Context c, CharSequence title)
60 | {
61 | if(recallAnimalTypeDialog == null)
62 | recallAnimalTypeDialog = new AlertDialog.Builder(c)
63 | .setTitle(title)
64 | .setSingleChoiceItems(RecallAnimalType.names, Config.recallAnimalType().ordinal(),
65 | new OnClickListener()
66 | {
67 | @Override
68 | public void onClick(DialogInterface p1, int p2)
69 | {
70 | Config.setRecallAnimalType(p2);
71 | }
72 | })
73 | .setPositiveButton("OK", null)
74 | .create();
75 | return recallAnimalTypeDialog;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/EditDialog.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.DialogInterface.OnClickListener;
7 | import android.widget.EditText;
8 | import pansong291.xposed.quickenergy.util.Config;
9 |
10 | public class EditDialog
11 | {
12 | private static AlertDialog editDialog;
13 | private static EditText edt;
14 | public enum EditMode
15 | { CHECK_INTERVAL, THREAD_COUNT, ADVANCE_TIME, COLLECT_INTERVAL,
16 | COLLECT_TIMEOUT, RETURN_WATER_30, RETURN_WATER_20, RETURN_WATER_10,
17 | MIN_EXCHANGE_COUNT, LATEST_EXCHANGE_TIME }
18 | private static EditMode mode;
19 |
20 | public static void showEditDialog(Context c, CharSequence title, EditMode em)
21 | {
22 | mode = em;
23 | try
24 | {
25 | getEditDialog(c).show();
26 | }catch(Throwable t)
27 | {
28 | editDialog = null;
29 | getEditDialog(c).show();
30 | }
31 | editDialog.setTitle(title);
32 | }
33 |
34 | private static AlertDialog getEditDialog(Context c)
35 | {
36 | if(editDialog == null)
37 | {
38 | edt = new EditText(c);
39 | editDialog = new AlertDialog.Builder(c)
40 | .setTitle("title")
41 | .setView(edt)
42 | .setPositiveButton(
43 | "OK",
44 | new OnClickListener()
45 | {
46 | Context context;
47 |
48 | public OnClickListener setData(Context c)
49 | {
50 | context = c;
51 | return this;
52 | }
53 |
54 | @Override
55 | public void onClick(DialogInterface p1, int p2)
56 | {
57 | try
58 | {
59 | int i = Integer.parseInt(edt.getText().toString());
60 | switch(mode)
61 | {
62 | case CHECK_INTERVAL:
63 | if(i > 0)
64 | Config.setCheckInterval(i * 60_000);
65 | break;
66 |
67 | case THREAD_COUNT:
68 | if(i >= 0)
69 | Config.setThreadCount(i);
70 | break;
71 |
72 | case ADVANCE_TIME:
73 | Config.setAdvanceTime(i);
74 | break;
75 |
76 | case COLLECT_INTERVAL:
77 | if(i >= 0)
78 | Config.setCollectInterval(i);
79 | break;
80 |
81 | case COLLECT_TIMEOUT:
82 | if(i > 0)
83 | Config.setCollectTimeout(i * 1_000);
84 | break;
85 |
86 | case RETURN_WATER_30:
87 | if(i >= 0)
88 | Config.setReturnWater30(i);
89 | break;
90 |
91 | case RETURN_WATER_20:
92 |
93 | if(i >= 0)
94 | Config.setReturnWater20(i);
95 | break;
96 |
97 | case RETURN_WATER_10:
98 | if(i >= 0)
99 | Config.setReturnWater10(i);
100 | break;
101 |
102 | case MIN_EXCHANGE_COUNT:
103 | if(i >= 0)
104 | Config.setMinExchangeCount(i);
105 | break;
106 |
107 | case LATEST_EXCHANGE_TIME:
108 | if(i >= 0 && i < 24)
109 | Config.setLatestExchangeTime(i);
110 | break;
111 |
112 | }
113 | }catch(Throwable t)
114 | {}
115 | }
116 | }.setData(c))
117 | .create();
118 | }
119 | String str = "";
120 | switch(mode)
121 | {
122 | case CHECK_INTERVAL:
123 | str = String.valueOf(Config.checkInterval() / 60_000);
124 | break;
125 |
126 | case THREAD_COUNT:
127 | str = String.valueOf(Config.threadCount());
128 | break;
129 |
130 | case ADVANCE_TIME:
131 | str = String.valueOf(Config.advanceTime());
132 | break;
133 |
134 | case COLLECT_INTERVAL:
135 | str = String.valueOf(Config.collectInterval());
136 | break;
137 |
138 | case COLLECT_TIMEOUT:
139 | str = String.valueOf(Config.collectTimeout() / 1_000);
140 | break;
141 |
142 | case RETURN_WATER_30:
143 | str = String.valueOf(Config.returnWater30());
144 | break;
145 |
146 | case RETURN_WATER_20:
147 | str = String.valueOf(Config.returnWater20());
148 | break;
149 |
150 | case RETURN_WATER_10:
151 | str = String.valueOf(Config.returnWater10());
152 | break;
153 |
154 | case MIN_EXCHANGE_COUNT:
155 | str = String.valueOf(Config.minExchangeCount());
156 | break;
157 |
158 | case LATEST_EXCHANGE_TIME:
159 | str = String.valueOf(Config.latestExchangeTime());
160 | break;
161 |
162 | }
163 | edt.setText(str);
164 | return editDialog;
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/HtmlViewerActivity.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.Activity;
4 | import android.content.ClipboardManager;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 | import android.webkit.WebChromeClient;
11 | import android.webkit.WebView;
12 | import android.widget.ProgressBar;
13 | import android.widget.Toast;
14 | import pansong291.xposed.quickenergy.R;
15 |
16 | public class HtmlViewerActivity extends Activity
17 | {
18 | MyWebView mWebView;
19 | ProgressBar pgb;
20 |
21 | @Override
22 | protected void onCreate(Bundle savedInstanceState)
23 | {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_html_viewer);
26 |
27 | mWebView = (MyWebView) findViewById(R.id.mwv_webview);
28 | pgb = (ProgressBar) findViewById(R.id.pgb_webview);
29 |
30 | mWebView.setWebChromeClient(
31 | new WebChromeClient()
32 | {
33 | @Override
34 | public void onProgressChanged(WebView view, int progress)
35 | {
36 | pgb.setProgress(progress);
37 | if(progress < 100)
38 | {
39 | setTitle("Loading...");
40 | pgb.setVisibility(View.VISIBLE);
41 | }else
42 | {
43 | setTitle(mWebView.getTitle());
44 | pgb.setVisibility(View.GONE);
45 | }
46 | }
47 | });
48 | mWebView.loadUrl(getIntent().getData().toString());
49 | }
50 |
51 | @Override
52 | public boolean onCreateOptionsMenu(Menu menu)
53 | {
54 | menu.add(0, 1, 0, "Open with other browser");
55 | menu.add(0, 2, 0, "Copy the url");
56 | menu.add(0, 3, 0, "Scroll to top");
57 | menu.add(0, 4, 0, "Scroll to bottom");
58 | return super.onCreateOptionsMenu(menu);
59 | }
60 |
61 | @Override
62 | public boolean onOptionsItemSelected(MenuItem item)
63 | {
64 | switch(item.getItemId())
65 | {
66 | case 1:
67 | Intent it = new Intent(Intent.ACTION_VIEW);
68 | it.addCategory(Intent.CATEGORY_DEFAULT);
69 | it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
70 | it.setDataAndType(getIntent().getData(), "text/html");
71 | startActivity(Intent.createChooser(it, "Choose a browser"));
72 | break;
73 |
74 | case 2:
75 | ClipboardManager cm = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
76 | cm.setText(mWebView.getUrl());
77 | Toast.makeText(this, "Copy success", 0).show();
78 | break;
79 |
80 | case 3:
81 | mWebView.scrollTo(0, 0);
82 | break;
83 |
84 | case 4:
85 | mWebView.scrollToBottom();
86 | break;
87 | }
88 | return true;
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/ListAdapter.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.CheckBox;
10 | import android.widget.TextView;
11 | import java.util.List;
12 | import pansong291.xposed.quickenergy.R;
13 |
14 | public class ListAdapter extends BaseAdapter
15 | {
16 | private static ListAdapter adapter;
17 |
18 | public static ListAdapter get(Context c)
19 | {
20 | if(adapter == null)
21 | adapter = new ListAdapter(c);
22 | return adapter;
23 | }
24 |
25 | Context context;
26 | List> list;
27 | List selects;
28 | int findIndex = -1;
29 | CharSequence findWord = null;
30 |
31 | private ListAdapter(Context c)
32 | {
33 | context = c;
34 | }
35 |
36 | public void setBaseList(List> l)
37 | {
38 | if(l != list) exitFind();
39 | list = l;
40 | }
41 |
42 | public void setSelectedList(List l)
43 | {
44 | selects = l;
45 | }
46 |
47 | public int findLast(CharSequence cs)
48 | {
49 | if(list == null || list.size() == 0) return -1;
50 | if(!cs.equals(findWord))
51 | {
52 | findIndex = -1;
53 | findWord = cs;
54 | }
55 | int i = findIndex;
56 | if(i < 0) i = list.size();
57 | for(;;)
58 | {
59 | i = (i + list.size() - 1) % list.size();
60 | AlipayId ai = (AlipayId) list.get(i);
61 | if(ai.name.contains(cs))
62 | {
63 | findIndex = i;
64 | break;
65 | }
66 | if(findIndex < 0 && i == 0)
67 | break;
68 | }
69 | notifyDataSetChanged();
70 | return findIndex;
71 | }
72 |
73 | public int findNext(CharSequence cs)
74 | {
75 | if(list == null || list.size() == 0) return -1;
76 | if(!cs.equals(findWord))
77 | {
78 | findIndex = -1;
79 | findWord = cs;
80 | }
81 | for(int i = findIndex;;)
82 | {
83 | i = (i + 1) % list.size();
84 | AlipayId ai = (AlipayId) list.get(i);
85 | if(ai.name.contains(cs))
86 | {
87 | findIndex = i;
88 | break;
89 | }
90 | if(findIndex < 0 && i == list.size() - 1)
91 | break;
92 | }
93 | notifyDataSetChanged();
94 | return findIndex;
95 | }
96 |
97 | public void exitFind()
98 | {
99 | findIndex = -1;
100 | }
101 |
102 | @Override
103 | public int getCount()
104 | {
105 | return list == null ? 0: list.size();
106 | }
107 |
108 | @Override
109 | public Object getItem(int p1)
110 | {
111 | return list.get(p1);
112 | }
113 |
114 | @Override
115 | public long getItemId(int p1)
116 | {
117 | return p1;
118 | }
119 |
120 | @Override
121 | public View getView(int p1, View p2, ViewGroup p3)
122 | {
123 | ViewHolder vh;
124 | if(p2 == null)
125 | {
126 | vh = new ViewHolder();
127 | p2 = LayoutInflater.from(context).inflate(R.layout.list_item, null);
128 | vh.tv = p2.findViewById(R.id.tv_idn);
129 | vh.cb = p2.findViewById(R.id.cb_list);
130 | p2.setTag(vh);
131 | }else
132 | {
133 | vh = (ViewHolder)p2.getTag();
134 | }
135 |
136 | AlipayId ai = (AlipayId) list.get(p1);
137 | vh.tv.setText(ai.name);
138 | vh.tv.setTextColor(findIndex == p1 ? Color.RED: Color.BLACK);
139 | vh.cb.setChecked(selects == null ? false: selects.contains(ai.id));
140 | return p2;
141 | }
142 |
143 | class ViewHolder
144 | {
145 | TextView tv;
146 | CheckBox cb;
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/ListDialog.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.AlertDialog;
4 | import android.content.Context;
5 | import android.content.DialogInterface;
6 | import android.content.DialogInterface.OnClickListener;
7 | import android.content.DialogInterface.OnShowListener;
8 | import android.content.Intent;
9 | import android.net.Uri;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.widget.AdapterView;
13 | import android.widget.AdapterView.OnItemClickListener;
14 | import android.widget.AdapterView.OnItemLongClickListener;
15 | import android.widget.Button;
16 | import android.widget.EditText;
17 | import android.widget.ListView;
18 | import android.widget.Toast;
19 | import java.util.List;
20 | import pansong291.xposed.quickenergy.R;
21 | import pansong291.xposed.quickenergy.util.Config;
22 | import pansong291.xposed.quickenergy.util.CooperationIdMap;
23 | import pansong291.xposed.quickenergy.util.FriendIdMap;
24 |
25 | public class ListDialog
26 | {
27 | static AlertDialog listDialog;
28 | static Button btn_find_last, btn_find_next;
29 | static EditText edt_find;
30 | static ListView lv_list;
31 | static List selectedList;
32 | static List countList;
33 | static ListAdapter.ViewHolder curViewHolder;
34 | static AlipayId curAlipayId;
35 |
36 | static AlertDialog edtDialog;
37 | static EditText edt_count;
38 |
39 | static AlertDialog optionsDialog;
40 | static AlertDialog deleteDialog;
41 |
42 | public static void show(Context c, CharSequence title, List> bl, List sl, List cl)
43 | {
44 | selectedList = sl;
45 | countList = cl;
46 | ListAdapter la = ListAdapter.get(c);
47 | la.setBaseList(bl);
48 | la.setSelectedList(selectedList);
49 | showListDialog(c, title);
50 | }
51 |
52 | private static void showListDialog(Context c, CharSequence title)
53 | {
54 | try
55 | {
56 | getListDialog(c).show();
57 | }catch(Throwable t)
58 | {
59 | listDialog = null;
60 | getListDialog(c).show();
61 | }
62 | listDialog.setTitle(title);
63 | }
64 |
65 | private static AlertDialog getListDialog(Context c)
66 | {
67 | if(listDialog == null)
68 | listDialog = new AlertDialog.Builder(c)
69 | .setTitle("title")
70 | .setView(getListView(c))
71 | .setPositiveButton("OK", null)
72 | .create();
73 | listDialog.setOnShowListener(
74 | new OnShowListener()
75 | {
76 | Context c;
77 |
78 | public OnShowListener setContext(Context c)
79 | {
80 | this.c = c;
81 | return this;
82 | }
83 |
84 | @Override
85 | public void onShow(DialogInterface p1)
86 | {
87 | ListAdapter.get(c).notifyDataSetChanged();
88 | }
89 | }.setContext(c));
90 | return listDialog;
91 | }
92 |
93 | private static View getListView(Context c)
94 | {
95 | View v = LayoutInflater.from(c).inflate(R.layout.dialog_list, null);
96 | OnBtnClickListener onBtnClickListener = new OnBtnClickListener();
97 | btn_find_last = v.findViewById(R.id.btn_find_last);
98 | btn_find_next = v.findViewById(R.id.btn_find_next);
99 | btn_find_last.setOnClickListener(onBtnClickListener);
100 | btn_find_next.setOnClickListener(onBtnClickListener);
101 | edt_find = v.findViewById(R.id.edt_find);
102 | lv_list = v.findViewById(R.id.lv_list);
103 | lv_list.setAdapter(ListAdapter.get(c));
104 | lv_list.setOnItemClickListener(
105 | new OnItemClickListener()
106 | {
107 | @Override
108 | public void onItemClick(AdapterView> p1, View p2, int p3, long p4)
109 | {
110 | curViewHolder = (ListAdapter.ViewHolder) p2.getTag();
111 | curAlipayId = (AlipayId) p1.getAdapter().getItem(p3);
112 | if(countList == null)
113 | {
114 | if(curViewHolder.cb.isChecked())
115 | {
116 | if(selectedList.contains(curAlipayId.id))
117 | selectedList.remove(curAlipayId.id);
118 | curViewHolder.cb.setChecked(false);
119 | }else
120 | {
121 | if(!selectedList.contains(curAlipayId.id))
122 | selectedList.add(curAlipayId.id);
123 | curViewHolder.cb.setChecked(true);
124 | }
125 | Config.hasChanged = true;
126 | }else
127 | {
128 | showEdtDialog(p1.getContext());
129 | }
130 | }
131 | });
132 | lv_list.setOnItemLongClickListener(
133 | new OnItemLongClickListener()
134 | {
135 | @Override
136 | public boolean onItemLongClick(AdapterView> p1, View p2, int p3, long p4)
137 | {
138 | curAlipayId = (AlipayId) p1.getAdapter().getItem(p3);
139 | if(curAlipayId instanceof AlipayCooperate)
140 | {
141 | showDeleteDialog(p1.getContext());
142 | }else
143 | {
144 | showOptionsDialog(p1.getContext());
145 | }
146 | return true;
147 | }
148 | });
149 | return v;
150 | }
151 |
152 | private static void showEdtDialog(Context c)
153 | {
154 | try
155 | {
156 | getEdtDialog(c).show();
157 | }catch(Throwable t)
158 | {
159 | edtDialog = null;
160 | getEdtDialog(c).show();
161 | }
162 | edtDialog.setTitle(curAlipayId.name);
163 | if(curAlipayId instanceof AlipayCooperate)
164 | edt_count.setHint("grams");
165 | else
166 | edt_count.setHint("count");
167 | int i = selectedList.indexOf(curAlipayId.id);
168 | if(i >= 0)
169 | edt_count.setText(String.valueOf(countList.get(i)));
170 | else
171 | edt_count.getText().clear();
172 | }
173 |
174 | private static AlertDialog getEdtDialog(Context c)
175 | {
176 | if(edtDialog == null)
177 | {
178 | OnClickListener listener = new OnClickListener()
179 | {
180 | Context c;
181 |
182 | public OnClickListener setContext(Context c)
183 | {
184 | this.c = c;
185 | return this;
186 | }
187 |
188 | @Override
189 | public void onClick(DialogInterface p1, int p2)
190 | {
191 | switch(p2)
192 | {
193 | case DialogInterface.BUTTON_POSITIVE:
194 | int count = 0;
195 | if(edt_count.length() > 0)
196 | try
197 | {
198 | count = Integer.parseInt(edt_count.getText().toString());
199 | }catch(Throwable t)
200 | {
201 | return;
202 | }
203 | int index = selectedList.indexOf(curAlipayId.id);
204 | if(count > 0)
205 | {
206 | if(index < 0)
207 | {
208 | selectedList.add(curAlipayId.id);
209 | countList.add(count);
210 | }else
211 | {
212 | countList.set(index, count);
213 | }
214 | curViewHolder.cb.setChecked(true);
215 | }else
216 | {
217 | if(index >= 0)
218 | {
219 | selectedList.remove(index);
220 | countList.remove(index);
221 | }
222 | curViewHolder.cb.setChecked(false);
223 | }
224 | Config.hasChanged = true;
225 | break;
226 | }
227 | ListAdapter.get(c).notifyDataSetChanged();
228 | }
229 | }.setContext(c);
230 | edt_count = new EditText(c);
231 | edtDialog = new AlertDialog.Builder(c)
232 | .setTitle("title")
233 | .setView(edt_count)
234 | .setPositiveButton("OK", listener)
235 | .setNegativeButton("CANCEL", null)
236 | .create();
237 | }
238 | return edtDialog;
239 | }
240 |
241 | private static void showOptionsDialog(Context c)
242 | {
243 | try
244 | {
245 | getOptionsDailog(c).show();
246 | }catch(Throwable t)
247 | {
248 | optionsDialog = null;
249 | getOptionsDailog(c).show();
250 | }
251 | }
252 |
253 | private static AlertDialog getOptionsDailog(Context c)
254 | {
255 | if(optionsDialog == null)
256 | {
257 | optionsDialog = new AlertDialog.Builder(c)
258 | .setTitle("Options")
259 | .setAdapter(
260 | OptionsAdapter.get(c), new OnClickListener()
261 | {
262 | Context c;
263 |
264 | public OnClickListener setContext(Context c)
265 | {
266 | this.c = c;
267 | return this;
268 | }
269 |
270 | @Override
271 | public void onClick(DialogInterface p1, int p2)
272 | {
273 | String url = null;
274 | switch(p2)
275 | {
276 | case 0:
277 | url = "alipays://platformapi/startapp?saId=10000007&qrcode=https%3A%2F%2F60000002.h5app.alipay.com%2Fwww%2Fhome.html%3FuserId%3D";
278 | break;
279 |
280 | case 1:
281 | url = "alipays://platformapi/startapp?saId=10000007&qrcode=https%3A%2F%2F66666674.h5app.alipay.com%2Fwww%2Findex.htm%3Fuid%3D";
282 | break;
283 |
284 | case 2:
285 | showDeleteDialog(c);
286 | }
287 | if(url != null && !url.isEmpty())
288 | {
289 | Intent it = new Intent(Intent.ACTION_VIEW, Uri.parse(url + curAlipayId.id));
290 | c.startActivity(it);
291 | }
292 | }
293 | }.setContext(c))
294 | .setNegativeButton("CANCEL", null)
295 | .create();
296 | }
297 | return optionsDialog;
298 | }
299 |
300 | private static void showDeleteDialog(Context c)
301 | {
302 | try
303 | {
304 | getDeleteDialog(c).show();
305 | }catch(Throwable t)
306 | {
307 | deleteDialog = null;
308 | getDeleteDialog(c).show();
309 | }
310 | deleteDialog.setTitle("Delete " + curAlipayId.name);
311 | }
312 |
313 | private static AlertDialog getDeleteDialog(Context c)
314 | {
315 | if(deleteDialog == null)
316 | {
317 | OnClickListener listener = new OnClickListener()
318 | {
319 | Context c;
320 |
321 | public OnClickListener setContext(Context c)
322 | {
323 | this.c = c;
324 | return this;
325 | }
326 |
327 | @Override
328 | public void onClick(DialogInterface p1, int p2)
329 | {
330 | switch(p2)
331 | {
332 | case DialogInterface.BUTTON_POSITIVE:
333 | if(curAlipayId instanceof AlipayUser)
334 | {
335 | FriendIdMap.removeIdMap(curAlipayId.id);
336 | AlipayUser.remove(curAlipayId.id);
337 | }else if(curAlipayId instanceof AlipayCooperate)
338 | {
339 | CooperationIdMap.removeIdMap(curAlipayId.id);
340 | AlipayCooperate.remove(curAlipayId.id);
341 | }
342 | if(selectedList.contains(curAlipayId.id))
343 | selectedList.remove(curAlipayId.id);
344 | ListAdapter.get(c).exitFind();
345 | break;
346 | }
347 | ListAdapter.get(c).notifyDataSetChanged();
348 | }
349 | }.setContext(c);
350 | deleteDialog = new AlertDialog.Builder(c)
351 | .setTitle("title")
352 | .setPositiveButton("OK", listener)
353 | .setNegativeButton("CANCEL", null)
354 | .create();
355 | }
356 | return deleteDialog;
357 | }
358 |
359 | static class OnBtnClickListener implements View.OnClickListener
360 | {
361 | @Override
362 | public void onClick(View p1)
363 | {
364 | if(edt_find.length() <= 0) return;
365 | ListAdapter la = ListAdapter.get(p1.getContext());
366 | int index = -1;
367 | switch(p1.getId())
368 | {
369 | case R.id.btn_find_last:
370 | // 下面Text要转String,不然判断equals会出问题
371 | index = la.findLast(edt_find.getText().toString());
372 | break;
373 |
374 | case R.id.btn_find_next:
375 | // 同上
376 | index = la.findNext(edt_find.getText().toString());
377 | break;
378 | }
379 | if(index < 0)
380 | {
381 | Toast.makeText(p1.getContext(), "Not found", Toast.LENGTH_SHORT).show();
382 | }else
383 | {
384 | lv_list.setSelection(index);
385 | }
386 | }
387 | }
388 |
389 | }
390 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/MainActivity.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.Activity;
4 | import android.content.ComponentName;
5 | import android.content.ContentResolver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.pm.PackageManager;
9 | import android.net.Uri;
10 | import android.os.Bundle;
11 | import android.view.Menu;
12 | import android.view.MenuItem;
13 | import android.view.View;
14 | import android.widget.Button;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 | import pansong291.xposed.quickenergy.R;
18 | import pansong291.xposed.quickenergy.util.FileUtils;
19 | import pansong291.xposed.quickenergy.util.RandomUtils;
20 | import pansong291.xposed.quickenergy.util.Statistics;
21 |
22 | public class MainActivity extends Activity
23 | {
24 | private static String[] strArray;
25 | TextView tv_statistics;
26 | Button btn_help;
27 |
28 | @Override
29 | protected void onCreate(Bundle savedInstanceState)
30 | {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_main);
33 | setModuleActive(false);
34 |
35 | tv_statistics = (TextView) findViewById(R.id.tv_statistics);
36 | btn_help = (Button) findViewById(R.id.btn_help);
37 | if(strArray == null)
38 | strArray = getResources().getStringArray(R.array.sentences);
39 | if(strArray != null)
40 | btn_help.setText(strArray[RandomUtils.nextInt(0, strArray.length)]);
41 | }
42 |
43 | @Override
44 | protected void onResume()
45 | {
46 | super.onResume();
47 | tv_statistics.setText(Statistics.getText());
48 | }
49 |
50 | public void onClick(View v)
51 | {
52 | String data = "file://";
53 | switch(v.getId())
54 | {
55 | case R.id.btn_forest_log:
56 | data += FileUtils.getForestLogFile().getAbsolutePath();
57 | break;
58 |
59 | case R.id.btn_farm_log:
60 | data += FileUtils.getFarmLogFile().getAbsolutePath();
61 | break;
62 |
63 | case R.id.btn_other_log:
64 | data += FileUtils.getOtherLogFile().getAbsolutePath();
65 | break;
66 |
67 | case R.id.btn_help:
68 | data = "https://github.com/pansong291/XQuickEnergy/wiki";
69 | break;
70 | }
71 | Intent it = new Intent(this, HtmlViewerActivity.class);
72 | it.setData(Uri.parse(data));
73 | startActivity(it);
74 | }
75 |
76 | @Override
77 | public boolean onCreateOptionsMenu(Menu menu)
78 | {
79 | int state = getPackageManager()
80 | .getComponentEnabledSetting(new ComponentName(this, getClass().getCanonicalName() + "Alias"));
81 | menu.add(0, 1, 0, "Hide the application icon")
82 | .setCheckable(true)
83 | .setChecked(state > PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
84 | menu.add(0, 2, 0, "Export the statistic file");
85 | menu.add(0, 3, 0, "Import the statistic file");
86 | menu.add(0, 4, 0, "Settings");
87 | return super.onCreateOptionsMenu(menu);
88 | }
89 |
90 | @Override
91 | public boolean onOptionsItemSelected(MenuItem item)
92 | {
93 | switch(item.getItemId())
94 | {
95 | case 1:
96 | int state = item.isChecked() ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
97 | getPackageManager()
98 | .setComponentEnabledSetting(new ComponentName(this, getClass().getCanonicalName() + "Alias"), state, PackageManager.DONT_KILL_APP);
99 | item.setChecked(!item.isChecked());
100 | break;
101 |
102 | case 2:
103 | if(FileUtils.copyTo(FileUtils.getStatisticsFile(), FileUtils.getExportedStatisticsFile()))
104 | Toast.makeText(this, "Export success", 0).show();
105 | break;
106 |
107 | case 3:
108 | if(FileUtils.copyTo(FileUtils.getExportedStatisticsFile(), FileUtils.getStatisticsFile()))
109 | {
110 | tv_statistics.setText(Statistics.getText());
111 | Toast.makeText(this, "Import success", 0).show();
112 | }
113 | break;
114 |
115 | case 4:
116 | startActivity(new Intent(this, SettingsActivity.class));
117 | break;
118 | }
119 | return super.onOptionsItemSelected(item);
120 | }
121 |
122 | private void setModuleActive(boolean b)
123 | {
124 | b = b || isExpModuleActive(this);
125 | TextView tv_unactive = (TextView) findViewById(R.id.tv_unactive);
126 | tv_unactive.setVisibility(b ? View.GONE : View.VISIBLE);
127 | }
128 |
129 | private static boolean isExpModuleActive(Context context)
130 | {
131 | boolean isExp = false;
132 | if(context == null)
133 | throw new IllegalArgumentException("context must not be null!!");
134 |
135 | try
136 | {
137 | ContentResolver contentResolver = context.getContentResolver();
138 | Uri uri = Uri.parse("content://me.weishu.exposed.CP/");
139 | Bundle result = null;
140 | try
141 | {
142 | result = contentResolver.call(uri, "active", null, null);
143 | }catch(RuntimeException e)
144 | {
145 | // TaiChi is killed, try invoke
146 | try
147 | {
148 | Intent intent = new Intent("me.weishu.exp.ACTION_ACTIVE");
149 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
150 | context.startActivity(intent);
151 | }catch(Throwable e1)
152 | {
153 | return false;
154 | }
155 | }
156 | if(result == null)
157 | result = contentResolver.call(uri, "active", null, null);
158 |
159 | if(result == null)
160 | return false;
161 | isExp = result.getBoolean("active", false);
162 | }catch(Throwable ignored)
163 | {
164 | }
165 | return isExp;
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/MyWebView.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.webkit.WebSettings;
6 | import android.webkit.WebView;
7 | import android.webkit.WebViewClient;
8 |
9 | public class MyWebView extends WebView
10 | {
11 | public MyWebView(Context c)
12 | {
13 | super(c);
14 | defInit();
15 | }
16 | public MyWebView(Context context, AttributeSet attrs)
17 | {
18 | super(context, attrs);
19 | defInit();
20 | }
21 |
22 | public MyWebView(Context context, AttributeSet attrs, int defStyleAttr)
23 | {
24 | super(context, attrs, defStyleAttr);
25 | defInit();
26 | }
27 |
28 | public MyWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
29 | {
30 | super(context, attrs, defStyleAttr, defStyleRes);
31 | defInit();
32 | }
33 |
34 | private void defInit()
35 | {
36 | getSettings().setSupportZoom(true);
37 | getSettings().setBuiltInZoomControls(true);
38 | getSettings().setDisplayZoomControls(false);
39 | getSettings().setUseWideViewPort(false);
40 | getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
41 | getSettings().setAllowFileAccess(true);
42 | getSettings().setJavaScriptEnabled(true);
43 | setWebViewClient(
44 | new WebViewClient()
45 | {
46 | public void onPageFinished(WebView view, String url)
47 | {
48 | if(url.endsWith(".log"))
49 | postDelayed(
50 | new Runnable()
51 | {
52 | @Override
53 | public void run()
54 | {
55 | if(Thread.interrupted()) return;
56 | if(getContentHeight() == 0)
57 | postDelayed(this, 100);
58 | else
59 | scrollToBottom();
60 | }
61 | }, 500);
62 | }
63 | });
64 | }
65 |
66 | public void scrollToBottom()
67 | {
68 | scrollTo(0, computeVerticalScrollRange());
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/OptionsAdapter.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 | import java.util.ArrayList;
10 |
11 | public class OptionsAdapter extends BaseAdapter
12 | {
13 | private static OptionsAdapter adapter;
14 |
15 | public static OptionsAdapter get(Context c)
16 | {
17 | if(adapter == null)
18 | adapter = new OptionsAdapter(c);
19 | return adapter;
20 | }
21 |
22 | Context context;
23 | ArrayList list;
24 |
25 | private OptionsAdapter(Context c)
26 | {
27 | context = c;
28 | list = new ArrayList<>();
29 | list.add("View the forest");
30 | list.add("View the farm");
31 | list.add("Delete");
32 | }
33 |
34 | @Override
35 | public int getCount()
36 | {
37 | return list == null ? 0 : list.size();
38 | }
39 |
40 | @Override
41 | public Object getItem(int p1)
42 | {
43 | return list.get(p1);
44 | }
45 |
46 | @Override
47 | public long getItemId(int p1)
48 | {
49 | return p1;
50 | }
51 |
52 | @Override
53 | public View getView(int p1, View p2, ViewGroup p3)
54 | {
55 | if(p2 == null)
56 | {
57 | p2 = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, null);
58 | }
59 | TextView txt = (TextView) p2;
60 | txt.setText(getItem(p1).toString());
61 | return p2;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/ui/SettingsActivity.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.ui;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.net.Uri;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.CheckBox;
10 | import android.widget.Toast;
11 | import pansong291.xposed.quickenergy.R;
12 | import pansong291.xposed.quickenergy.util.Config;
13 | import pansong291.xposed.quickenergy.util.CooperationIdMap;
14 | import pansong291.xposed.quickenergy.util.FriendIdMap;
15 |
16 | public class SettingsActivity extends Activity
17 | {
18 | CheckBox cb_immediateEffect, cb_recordLog, cb_showToast,
19 | cb_stayAwake, cb_autoRestart,
20 | cb_collectEnergy, cb_helpFriendCollect, cb_receiveForestTaskAward,
21 | cb_cooperateWater,
22 | cb_enableFarm, cb_rewardFriend, cb_sendBackAnimal,
23 | cb_receiveFarmToolReward, cb_useNewEggTool, cb_harvestProduce,
24 | cb_donation, cb_answerQuestion, cb_receiveFarmTaskAward,
25 | cb_feedAnimal, cb_useAccelerateTool, cb_notifyFriend,
26 | cb_receivePoint, cb_openTreasureBox, cb_donateCharityCoin,
27 | cb_kbSignIn;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState)
31 | {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_settings);
34 |
35 | Config.shouldReload = true;
36 | FriendIdMap.shouldReload = true;
37 | CooperationIdMap.shouldReload = true;
38 |
39 | cb_immediateEffect = (CheckBox) findViewById(R.id.cb_immediateEffect);
40 | cb_recordLog = (CheckBox) findViewById(R.id.cb_recordLog);
41 | cb_showToast = (CheckBox) findViewById(R.id.cb_showToast);
42 | cb_stayAwake = (CheckBox) findViewById(R.id.cb_stayAwake);
43 | cb_autoRestart = (CheckBox) findViewById(R.id.cb_autoRestart);
44 | cb_collectEnergy = (CheckBox) findViewById(R.id.cb_collectEnergy);
45 | cb_helpFriendCollect = (CheckBox) findViewById(R.id.cb_helpFriendCollect);
46 | cb_receiveForestTaskAward = (CheckBox) findViewById(R.id.cb_receiveForestTaskAward);
47 | cb_cooperateWater = (CheckBox) findViewById(R.id.cb_cooperateWater);
48 | cb_enableFarm = (CheckBox) findViewById(R.id.cb_enableFarm);
49 | cb_rewardFriend = (CheckBox) findViewById(R.id.cb_rewardFriend);
50 | cb_sendBackAnimal = (CheckBox) findViewById(R.id.cb_sendBackAnimal);
51 | cb_receiveFarmToolReward = (CheckBox) findViewById(R.id.cb_receiveFarmToolReward);
52 | cb_useNewEggTool = (CheckBox) findViewById(R.id.cb_useNewEggTool);
53 | cb_harvestProduce = (CheckBox) findViewById(R.id.cb_harvestProduce);
54 | cb_donation = (CheckBox) findViewById(R.id.cb_donation);
55 | cb_answerQuestion = (CheckBox) findViewById(R.id.cb_answerQuestion);
56 | cb_receiveFarmTaskAward = (CheckBox) findViewById(R.id.cb_receiveFarmTaskAward);
57 | cb_feedAnimal = (CheckBox) findViewById(R.id.cb_feedAnimal);
58 | cb_useAccelerateTool = (CheckBox) findViewById(R.id.cb_useAccelerateTool);
59 | cb_notifyFriend = (CheckBox) findViewById(R.id.cb_notifyFriend);
60 | cb_receivePoint = (CheckBox) findViewById(R.id.cb_receivePoint);
61 | cb_openTreasureBox = (CheckBox) findViewById(R.id.cb_openTreasureBox);
62 | cb_donateCharityCoin = (CheckBox) findViewById(R.id.cb_donateCharityCoin);
63 | cb_kbSignIn = (CheckBox) findViewById(R.id.cb_kbSignIn);
64 | }
65 |
66 | @Override
67 | protected void onResume()
68 | {
69 | super.onResume();
70 | cb_immediateEffect.setChecked(Config.immediateEffect());
71 | cb_recordLog.setChecked(Config.recordLog());
72 | cb_showToast.setChecked(Config.showToast());
73 | cb_stayAwake.setChecked(Config.stayAwake());
74 | cb_autoRestart.setChecked(Config.autoRestart());
75 | cb_collectEnergy.setChecked(Config.collectEnergy());
76 | cb_helpFriendCollect.setChecked(Config.helpFriendCollect());
77 | cb_receiveForestTaskAward.setChecked(Config.receiveForestTaskAward());
78 | cb_cooperateWater.setChecked(Config.cooperateWater());
79 | cb_enableFarm.setChecked(Config.enableFarm());
80 | cb_rewardFriend.setChecked(Config.rewardFriend());
81 | cb_sendBackAnimal.setChecked(Config.sendBackAnimal());
82 | cb_receiveFarmToolReward.setChecked(Config.receiveFarmToolReward());
83 | cb_useNewEggTool.setChecked(Config.useNewEggTool());
84 | cb_harvestProduce.setChecked(Config.harvestProduce());
85 | cb_donation.setChecked(Config.donation());
86 | cb_answerQuestion.setChecked(Config.answerQuestion());
87 | cb_receiveFarmTaskAward.setChecked(Config.receiveFarmTaskAward());
88 | cb_feedAnimal.setChecked(Config.feedAnimal());
89 | cb_useAccelerateTool.setChecked(Config.useAccelerateTool());
90 | cb_notifyFriend.setChecked(Config.notifyFriend());
91 | cb_receivePoint.setChecked(Config.receivePoint());
92 | cb_openTreasureBox.setChecked(Config.openTreasureBox());
93 | cb_donateCharityCoin.setChecked(Config.donateCharityCoin());
94 | cb_kbSignIn.setChecked(Config.kbSginIn());
95 | }
96 |
97 | public void onClick(View v)
98 | {
99 | CheckBox cb = v instanceof CheckBox ? (CheckBox)v : null;
100 | Button btn = v instanceof Button ? (Button)v : null;
101 | switch(v.getId())
102 | {
103 | case R.id.cb_immediateEffect:
104 | Config.setImmediateEffect(cb.isChecked());
105 | break;
106 |
107 | case R.id.cb_recordLog:
108 | Config.setRecordLog(cb.isChecked());
109 | break;
110 |
111 | case R.id.cb_showToast:
112 | Config.setShowToast(cb.isChecked());
113 | break;
114 |
115 | case R.id.cb_stayAwake:
116 | Config.setStayAwake(cb.isChecked());
117 | break;
118 |
119 | case R.id.cb_autoRestart:
120 | Config.setAutoRestart(cb.isChecked());
121 | break;
122 |
123 | case R.id.cb_collectEnergy:
124 | Config.setCollectEnergy(cb.isChecked());
125 | break;
126 |
127 | case R.id.btn_checkInterval:
128 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.CHECK_INTERVAL);
129 | break;
130 |
131 | case R.id.btn_threadCount:
132 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.THREAD_COUNT);
133 | break;
134 |
135 | case R.id.btn_advanceTime:
136 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.ADVANCE_TIME);
137 | break;
138 |
139 | case R.id.btn_collectInterval:
140 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.COLLECT_INTERVAL);
141 | break;
142 |
143 | case R.id.btn_collectTimeout:
144 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.COLLECT_TIMEOUT);
145 | break;
146 |
147 | case R.id.btn_returnWater30:
148 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.RETURN_WATER_30);
149 | break;
150 |
151 | case R.id.btn_returnWater20:
152 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.RETURN_WATER_20);
153 | break;
154 |
155 | case R.id.btn_returnWater10:
156 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.RETURN_WATER_10);
157 | break;
158 |
159 | case R.id.cb_helpFriendCollect:
160 | Config.setHelpFriendCollect(cb.isChecked());
161 | break;
162 |
163 | case R.id.btn_dontCollectList:
164 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getDontCollectList(), null);
165 | break;
166 |
167 | case R.id.btn_dontHelpCollectList:
168 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getDontHelpCollectList(), null);
169 | break;
170 |
171 | case R.id.cb_receiveForestTaskAward:
172 | Config.setReceiveForestTaskAward(cb.isChecked());
173 | break;
174 |
175 | case R.id.btn_waterFriendList:
176 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getWaterFriendList(), Config.getWaterCountList());
177 | break;
178 |
179 | case R.id.cb_cooperateWater:
180 | Config.setCooperateWater(cb.isChecked());
181 | break;
182 |
183 | case R.id.btn_cooperateWaterList:
184 | ListDialog.show(this, btn.getText(), AlipayCooperate.getList(), Config.getCooperateWaterList(), Config.getcooperateWaterNumList());
185 | break;
186 |
187 | case R.id.cb_enableFarm:
188 | Config.setEnableFarm(cb.isChecked());
189 | break;
190 |
191 | case R.id.cb_rewardFriend:
192 | Config.setRewardFriend(cb.isChecked());
193 | break;
194 |
195 | case R.id.cb_sendBackAnimal:
196 | Config.setSendBackAnimal(cb.isChecked());
197 | break;
198 |
199 | case R.id.btn_sendType:
200 | ChoiceDialog.showSendType(this, btn.getText());
201 | break;
202 |
203 | case R.id.btn_dontSendFriendList:
204 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getDontSendFriendList(), null);
205 | break;
206 |
207 | case R.id.btn_recallAnimalType:
208 | ChoiceDialog.showRecallAnimalType(this, btn.getText());
209 | break;
210 |
211 | case R.id.cb_receiveFarmToolReward:
212 | Config.setReceiveFarmToolReward(cb.isChecked());
213 | break;
214 |
215 | case R.id.cb_useNewEggTool:
216 | Config.setUseNewEggTool(cb.isChecked());
217 | break;
218 |
219 | case R.id.cb_harvestProduce:
220 | Config.setHarvestProduce(cb.isChecked());
221 | break;
222 |
223 | case R.id.cb_donation:
224 | Config.setDonation(cb.isChecked());
225 | break;
226 |
227 | case R.id.cb_answerQuestion:
228 | Config.setAnswerQuestion(cb.isChecked());
229 | break;
230 |
231 | case R.id.cb_receiveFarmTaskAward:
232 | Config.setReceiveFarmTaskAward(cb.isChecked());
233 | break;
234 |
235 | case R.id.cb_feedAnimal:
236 | Config.setFeedAnimal(cb.isChecked());
237 | break;
238 |
239 | case R.id.cb_useAccelerateTool:
240 | Config.setUseAccelerateTool(cb.isChecked());
241 | break;
242 |
243 | case R.id.btn_feedFriendAnimalList:
244 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getFeedFriendAnimalList(), Config.getFeedFriendCountList());
245 | break;
246 |
247 | case R.id.cb_notifyFriend:
248 | Config.setNotifyFriend(cb.isChecked());
249 | break;
250 |
251 | case R.id.btn_dontNotifyFriendList:
252 | ListDialog.show(this, btn.getText(), AlipayUser.getList(), Config.getDontNotifyFriendList(), null);
253 | break;
254 |
255 | case R.id.cb_receivePoint:
256 | Config.setReceivePoint(cb.isChecked());
257 | break;
258 |
259 | case R.id.btn_donation_developer:
260 | Intent it2 = new Intent(Intent.ACTION_VIEW, Uri.parse("alipays://platformapi/startapp?saId=10000007&qrcode=https%3A%2F%2Fqr.alipay.com%2Ftsx00339eflkuhhtfctcn48"));
261 | startActivity(it2);
262 | break;
263 |
264 | case R.id.cb_openTreasureBox:
265 | Config.setOpenTreasureBox(cb.isChecked());
266 | break;
267 |
268 | case R.id.cb_donateCharityCoin:
269 | Config.setDonateCharityCoin(cb.isChecked());
270 | break;
271 |
272 | case R.id.btn_minExchangeCount:
273 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.MIN_EXCHANGE_COUNT);
274 | break;
275 |
276 | case R.id.btn_latestExchangeTime:
277 | EditDialog.showEditDialog(this, btn.getText(), EditDialog.EditMode.LATEST_EXCHANGE_TIME);
278 | break;
279 |
280 | case R.id.cb_kbSignIn:
281 | Config.setKbSginIn(cb.isChecked());
282 | break;
283 | }
284 | }
285 |
286 | @Override
287 | protected void onPause()
288 | {
289 | super.onPause();
290 | if(Config.hasChanged)
291 | {
292 | Config.hasChanged = !Config.saveConfigFile();
293 | Toast.makeText(this, "Configuration saved", 0).show();
294 | }
295 | FriendIdMap.saveIdMap();
296 | CooperationIdMap.saveIdMap();
297 | }
298 |
299 | }
300 |
301 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/CooperationIdMap.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import java.util.TreeMap;
8 |
9 | public class CooperationIdMap
10 | {
11 | private static final String TAG = CooperationIdMap.class.getCanonicalName();
12 |
13 | public static boolean shouldReload = false;
14 |
15 | private static Map idMap;
16 | private static boolean hasChanged = false;
17 |
18 | public static void putIdMap(String key, String value)
19 | {
20 | if(key == null || key.isEmpty()) return;
21 | if(getIdMap().containsKey(key))
22 | {
23 | if(!getIdMap().get(key).equals(value))
24 | {
25 | getIdMap().remove(key);
26 | getIdMap().put(key, value);
27 | hasChanged = true;
28 | }
29 | }else
30 | {
31 | getIdMap().put(key, value);
32 | hasChanged = true;
33 | }
34 | }
35 |
36 | public static void removeIdMap(String key)
37 | {
38 | if(key == null || key.isEmpty()) return;
39 | if(getIdMap().containsKey(key))
40 | {
41 | getIdMap().remove(key);
42 | hasChanged = true;
43 | }
44 | }
45 |
46 | public static void clearIdMap()
47 | {
48 | getIdMap().clear();
49 | hasChanged = true;
50 | }
51 |
52 | public static boolean saveIdMap()
53 | {
54 | if(hasChanged)
55 | {
56 | StringBuilder sb = new StringBuilder();
57 | Set idSet = getIdMap().entrySet();
58 | for(Map.Entry entry: idSet)
59 | {
60 | sb.append(entry.getKey());
61 | sb.append(':');
62 | sb.append(entry.getValue());
63 | sb.append('\n');
64 | }
65 | hasChanged = !FileUtils.write2File(sb.toString(), FileUtils.getCooperationIdMapFile());
66 | }
67 | return hasChanged;
68 | }
69 |
70 | public static String getNameById(String id)
71 | {
72 | if(id == null || id.isEmpty()) return id;
73 | if(getIdMap().containsKey(id))
74 | {
75 | id = getIdMap().get(id).toString();
76 | }
77 | return id;
78 | }
79 |
80 | public static Map getIdMap()
81 | {
82 | if(idMap == null || shouldReload)
83 | {
84 | shouldReload = false;
85 | idMap = new TreeMap<>();
86 | String str = FileUtils.readFromFile(FileUtils.getCooperationIdMapFile());
87 | if(str != null && str.length() > 0)
88 | {
89 | try
90 | {
91 | String[] idSet = str.split("\n");
92 | for(String s: idSet)
93 | {
94 | Log.i(TAG, s);
95 | int ind = s.indexOf(":");
96 | idMap.put(s.substring(0, ind), s.substring(ind + 1));
97 | }
98 | }catch(Throwable t)
99 | {
100 | Log.printStackTrace(TAG, t);
101 | idMap.clear();
102 | }
103 | }
104 | }
105 | return idMap;
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/FileUtils.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import android.os.Environment;
4 | import java.io.Closeable;
5 | import java.io.File;
6 | import java.io.FileReader;
7 | import java.io.FileWriter;
8 |
9 | public class FileUtils
10 | {
11 | private static final String TAG = FileUtils.class.getCanonicalName();
12 | private static File androidDirectory;
13 | private static File configDirectory;
14 | private static File configFile;
15 | private static File friendIdMapFile;
16 | private static File cooperationIdMapFile;
17 | private static File statisticsFile;
18 | private static File exportedStatisticsFile;
19 | private static File forestLogFile;
20 | private static File farmLogFile;
21 | private static File otherLogFile;
22 | private static File simpleLogFile;
23 | private static File runtimeLogFile;
24 |
25 | public static File getAndroidDirectoryFile()
26 | {
27 | if(androidDirectory == null)
28 | {
29 | androidDirectory = new File(Environment.getExternalStorageDirectory(), "Android");
30 | if(!androidDirectory.exists())
31 | {
32 | androidDirectory.mkdirs();
33 | }
34 | }
35 | return androidDirectory;
36 | }
37 |
38 | public static File getConfigDirectoryFile()
39 | {
40 | if(configDirectory == null)
41 | {
42 | configDirectory = new File(getAndroidDirectoryFile(), "data/pansong291.xposed.quickenergy");
43 | if(configDirectory.exists())
44 | {
45 | if(configDirectory.isFile())
46 | {
47 | configDirectory.delete();
48 | configDirectory.mkdirs();
49 | }
50 | }else
51 | {
52 | configDirectory.mkdirs();
53 | }
54 | }
55 | return configDirectory;
56 | }
57 |
58 | public static File getConfigFile()
59 | {
60 | if(configFile == null)
61 | {
62 | configFile = new File(getConfigDirectoryFile(), "config.json");
63 | if(configFile.exists() && configFile.isDirectory())
64 | configFile.delete();
65 | }
66 | return configFile;
67 | }
68 |
69 | public static File getFriendIdMapFile()
70 | {
71 | if(friendIdMapFile == null)
72 | {
73 | friendIdMapFile = new File(getConfigDirectoryFile(), "friendId.list");
74 | if(friendIdMapFile.exists() && friendIdMapFile.isDirectory())
75 | friendIdMapFile.delete();
76 | }
77 | return friendIdMapFile;
78 | }
79 |
80 | public static File getCooperationIdMapFile()
81 | {
82 | if(cooperationIdMapFile == null)
83 | {
84 | cooperationIdMapFile = new File(getConfigDirectoryFile(), "cooperationId.list");
85 | if(cooperationIdMapFile.exists() && cooperationIdMapFile.isDirectory())
86 | cooperationIdMapFile.delete();
87 | }
88 | return cooperationIdMapFile;
89 | }
90 |
91 | public static File getStatisticsFile()
92 | {
93 | if(statisticsFile == null)
94 | {
95 | statisticsFile = new File(getConfigDirectoryFile(), "statistics.json");
96 | if(statisticsFile.exists() && statisticsFile.isDirectory())
97 | statisticsFile.delete();
98 | }
99 | return statisticsFile;
100 | }
101 |
102 | public static File getExportedStatisticsFile()
103 | {
104 | if(exportedStatisticsFile == null)
105 | {
106 | exportedStatisticsFile = new File(getAndroidDirectoryFile(), "statistics.json");
107 | if(exportedStatisticsFile.exists() && exportedStatisticsFile.isDirectory())
108 | exportedStatisticsFile.delete();
109 | }
110 | return exportedStatisticsFile;
111 | }
112 |
113 | public static File getForestLogFile()
114 | {
115 | if(forestLogFile == null)
116 | {
117 | forestLogFile = new File(getConfigDirectoryFile(), "forest.log");
118 | if(forestLogFile.exists() && forestLogFile.isDirectory())
119 | forestLogFile.delete();
120 | if(!forestLogFile.exists())
121 | try
122 | {
123 | forestLogFile.createNewFile();
124 | }catch(Throwable t)
125 | {}
126 | }
127 | return forestLogFile;
128 | }
129 |
130 | public static File getFarmLogFile()
131 | {
132 | if(farmLogFile == null)
133 | {
134 | farmLogFile = new File(getConfigDirectoryFile(), "farm.log");
135 | if(farmLogFile.exists() && farmLogFile.isDirectory())
136 | farmLogFile.delete();
137 | if(!farmLogFile.exists())
138 | try
139 | {
140 | farmLogFile.createNewFile();
141 | }catch(Throwable t)
142 | {}
143 | }
144 | return farmLogFile;
145 | }
146 |
147 | public static File getOtherLogFile()
148 | {
149 | if(otherLogFile == null)
150 | {
151 | otherLogFile = new File(getConfigDirectoryFile(), "other.log");
152 | if(otherLogFile.exists() && otherLogFile.isDirectory())
153 | otherLogFile.delete();
154 | if(!otherLogFile.exists())
155 | try
156 | {
157 | otherLogFile.createNewFile();
158 | }catch(Throwable t)
159 | {}
160 | }
161 | return otherLogFile;
162 | }
163 |
164 | public static File getSimpleLogFile()
165 | {
166 | if(simpleLogFile == null)
167 | {
168 | simpleLogFile = new File(getConfigDirectoryFile(), "simple.log");
169 | if(simpleLogFile.exists() && simpleLogFile.isDirectory())
170 | simpleLogFile.delete();
171 | }
172 | return simpleLogFile;
173 | }
174 |
175 | public static File getRuntimeLogFile()
176 | {
177 | if(runtimeLogFile == null)
178 | {
179 | runtimeLogFile = new File(getConfigDirectoryFile(), "runtime.log");
180 | if(runtimeLogFile.exists() && runtimeLogFile.isDirectory())
181 | runtimeLogFile.delete();
182 | }
183 | return runtimeLogFile;
184 | }
185 |
186 | public static File getBackupFile(File f)
187 | {
188 | return new File(f.getAbsolutePath() + ".bak");
189 | }
190 |
191 | public static String readFromFile(File f)
192 | {
193 | StringBuilder result = new StringBuilder();
194 | FileReader fr = null;
195 | try
196 | {
197 | fr = new FileReader(f);
198 | char[] chs = new char[1024];
199 | int len = 0;
200 | while((len = fr.read(chs)) >= 0)
201 | {
202 | result .append(chs, 0, len);
203 | }
204 | }catch(Throwable t)
205 | {
206 | Log.printStackTrace(TAG, t);
207 | }
208 | close(fr, f);
209 | return result.toString();
210 | }
211 |
212 | public static boolean append2SimpleLogFile(String s)
213 | {
214 | if(getSimpleLogFile().length() > 31_457_280) // 30MB
215 | getSimpleLogFile().delete();
216 | return append2File(Log.getFormatDateTime() + " " + s + "\n", getSimpleLogFile());
217 | }
218 |
219 | public static boolean append2RuntimeLogFile(String s)
220 | {
221 | if(getRuntimeLogFile().length() > 31_457_280) // 30MB
222 | getRuntimeLogFile().delete();
223 | return append2File(Log.getFormatDateTime() + " " + s + "\n", getRuntimeLogFile());
224 | }
225 |
226 | public static boolean write2File(String s, File f)
227 | {
228 | boolean success = false;
229 | FileWriter fw = null;
230 | try
231 | {
232 | fw = new FileWriter(f);
233 | fw.write(s);
234 | fw.flush();
235 | success = true;
236 | }catch(Throwable t)
237 | {
238 | if(!f.equals(getRuntimeLogFile()))
239 | Log.printStackTrace(TAG, t);
240 | }
241 | close(fw, f);
242 | return success;
243 | }
244 |
245 | public static boolean append2File(String s, File f)
246 | {
247 | boolean success = false;
248 | FileWriter fw = null;
249 | try
250 | {
251 | fw = new FileWriter(f, true);
252 | fw.append(s);
253 | fw.flush();
254 | success = true;
255 | }catch(Throwable t)
256 | {
257 | if(!f.equals(getRuntimeLogFile()))
258 | Log.printStackTrace(TAG, t);
259 | }
260 | close(fw, f);
261 | return success;
262 | }
263 |
264 | public static boolean copyTo(File f1, File f2)
265 | {
266 | return write2File(readFromFile(f1), f2);
267 | }
268 |
269 | public static void close(Closeable c, File f)
270 | {
271 | try
272 | {
273 | if(c != null) c.close();
274 | }catch(Throwable t)
275 | {
276 | if(!f.equals(getRuntimeLogFile()))
277 | Log.printStackTrace(TAG, t);
278 | }
279 | }
280 |
281 | }
282 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/FriendIdMap.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.Map;
6 | import java.util.Set;
7 | import java.util.TreeMap;
8 |
9 | public class FriendIdMap
10 | {
11 | private static final String TAG = FriendIdMap.class.getCanonicalName();
12 |
13 | public static boolean shouldReload = false;
14 |
15 | public static String currentUid;
16 |
17 | private static Map idMap;
18 | private static boolean hasChanged = false;
19 | private static String selfId;
20 |
21 | public static void putIdMap(String key, String value)
22 | {
23 | if(key == null || key.isEmpty()) return;
24 | if(getIdMap().containsKey(key))
25 | {
26 | if(!getIdMap().get(key).equals(value))
27 | {
28 | getIdMap().remove(key);
29 | getIdMap().put(key, value);
30 | hasChanged = true;
31 | }
32 | }else
33 | {
34 | getIdMap().put(key, value);
35 | hasChanged = true;
36 | }
37 | }
38 |
39 | public static void removeIdMap(String key)
40 | {
41 | if(key == null || key.isEmpty()) return;
42 | if(getIdMap().containsKey(key))
43 | {
44 | getIdMap().remove(key);
45 | hasChanged = true;
46 | }
47 | }
48 |
49 | public static boolean saveIdMap()
50 | {
51 | if(hasChanged)
52 | {
53 | StringBuilder sb = new StringBuilder();
54 | Set idSet = getIdMap().entrySet();
55 | for(Map.Entry entry: idSet)
56 | {
57 | sb.append(entry.getKey());
58 | sb.append(':');
59 | sb.append(entry.getValue());
60 | sb.append('\n');
61 | }
62 | hasChanged = !FileUtils.write2File(sb.toString(), FileUtils.getFriendIdMapFile());
63 | }
64 | return hasChanged;
65 | }
66 |
67 | private static String getSelfId()
68 | {
69 | if(selfId == null)
70 | {
71 | Set idSet = getIdMap().entrySet();
72 | for(Map.Entry entry: idSet)
73 | if(!entry.getValue().toString().contains("*"))
74 | {
75 | selfId = entry.getKey().toString();
76 | break;
77 | }
78 | }
79 | return selfId;
80 | }
81 |
82 | public static String getNameById(String id)
83 | {
84 | if(id == null || id.isEmpty()) return id;
85 | if(getIdMap().containsKey(id))
86 | {
87 | String n = getIdMap().get(id).toString();
88 | int ind = n.lastIndexOf('(');
89 | if(ind > 0) n = n.substring(0, ind);
90 | if(!n.equals("*")) return n;
91 | }else
92 | {
93 | putIdMap(id, "*(*)");
94 | }
95 | return id;
96 | }
97 |
98 | public static String[] getUnknownIds()
99 | {
100 | List idList = new ArrayList();
101 | Set idSet = getIdMap().entrySet();
102 | for(Map.Entry entry: idSet)
103 | if(entry.getValue().toString().contains("(*)"))
104 | idList.add(entry.getKey().toString());
105 | if(idList.size() > 0)
106 | {
107 | String[] ids = new String[idList.size()];
108 | for(int i = 0; i < ids.length; i++)
109 | {
110 | ids[i] = idList.get(i);
111 | Log.i(TAG, "未知id: " + ids[i]);
112 | }
113 | return ids;
114 | }
115 | return null;
116 | }
117 |
118 | public static Map getIdMap()
119 | {
120 | if(idMap == null || shouldReload)
121 | {
122 | shouldReload = false;
123 | idMap = new TreeMap<>();
124 | String str = FileUtils.readFromFile(FileUtils.getFriendIdMapFile());
125 | if(str != null && str.length() > 0)
126 | {
127 | try
128 | {
129 | String[] idSet = str.split("\n");
130 | for(String s: idSet)
131 | {
132 | Log.i(TAG, s);
133 | int ind = s.indexOf(":");
134 | idMap.put(s.substring(0, ind), s.substring(ind + 1));
135 | }
136 | }catch(Throwable t)
137 | {
138 | Log.printStackTrace(TAG, t);
139 | idMap.clear();
140 | }
141 | }
142 | }
143 | return idMap;
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/Log.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import de.robv.android.xposed.XposedBridge;
4 | import java.text.SimpleDateFormat;
5 | import java.util.Date;
6 |
7 | public class Log
8 | {
9 | private static final String TAG = Log.class.getCanonicalName();
10 | private static SimpleDateFormat sdf;
11 |
12 | public static void i(String tag, String s)
13 | {
14 | StringBuilder sb = new StringBuilder(tag + ", " + s);
15 | try
16 | {
17 | for(int i = 0; i < sb.length(); i += 2000)
18 | {
19 | if(sb.length() < i + 2000)
20 | XposedBridge.log(sb.substring(i, sb.length()));
21 | else
22 | XposedBridge.log(sb.substring(i, i + 2000));
23 | }
24 | }catch(Throwable t)
25 | {
26 | // when hooking self, this XposedBridge.class will
27 | // not be found, ignore it.
28 | android.util.Log.i(tag, s);
29 | }
30 | FileUtils.append2RuntimeLogFile(sb.toString());
31 | }
32 |
33 | public static void printStackTrace(String tag, Throwable t)
34 | {
35 | Log.i(tag, android.util.Log.getStackTraceString(t));
36 | }
37 |
38 | public static boolean forest(String s)
39 | {
40 | recordLog(s, "");
41 | return FileUtils.append2File(getFormatTime() + " " + s + "\n", FileUtils.getForestLogFile());
42 | }
43 |
44 | public static boolean farm(String s)
45 | {
46 | recordLog(s, "");
47 | return FileUtils.append2File(getFormatTime() + " " + s + "\n", FileUtils.getFarmLogFile());
48 | }
49 |
50 | public static boolean other(String s)
51 | {
52 | recordLog(s, "");
53 | return FileUtils.append2File(getFormatTime() + " " + s + "\n", FileUtils.getOtherLogFile());
54 | }
55 |
56 | public static boolean recordLog(String str, String str2)
57 | {
58 | Log.i(TAG, str + str2);
59 | if(!Config.recordLog()) return false;
60 | return FileUtils.append2SimpleLogFile(str);
61 | }
62 |
63 | public static String getFormatDateTime()
64 | {
65 | if(sdf == null) sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
66 | return sdf.format(new Date());
67 | }
68 |
69 | public static String getFormatDate()
70 | {
71 | return getFormatDateTime().split(" ")[0];
72 | }
73 |
74 | public static String getFormatTime()
75 | {
76 | return getFormatDateTime().split(" ")[1];
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/RandomUtils.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import java.util.Random;
4 |
5 | public class RandomUtils
6 | {
7 | private static final Random rnd = new Random();
8 |
9 | public static int delay()
10 | {
11 | return nextInt(100, 300);
12 | }
13 |
14 | public static int nextInt(int min, int max)
15 | {
16 | return rnd.nextInt(max - min) + min;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/java/pansong291/xposed/quickenergy/util/Statistics.java:
--------------------------------------------------------------------------------
1 | package pansong291.xposed.quickenergy.util;
2 |
3 | import java.util.ArrayList;
4 | import org.json.JSONArray;
5 | import org.json.JSONObject;
6 |
7 | public class Statistics
8 | {
9 | public enum TimeType
10 | { YEAR, MONTH, DAY }
11 |
12 | public enum DataType
13 | { TIME, COLLECTED, HELPED, WATERED }
14 |
15 | private class TimeStatistics
16 | {
17 | int time;
18 | int collected, helped, watered;
19 |
20 | TimeStatistics(int i)
21 | {
22 | reset(i);
23 | }
24 |
25 | public void reset(int i)
26 | {
27 | time = i;
28 | collected = 0;
29 | helped = 0;
30 | watered = 0;
31 | }
32 | }
33 |
34 | private class WaterFriendLog
35 | {
36 | String userId;
37 | int waterCount = 0;
38 | public WaterFriendLog(String id)
39 | {
40 | userId = id;
41 | }
42 | }
43 |
44 | private class FeedFriendLog
45 | {
46 | String userId;
47 | int feedCount = 0;
48 | public FeedFriendLog(String id)
49 | {
50 | userId = id;
51 | }
52 | }
53 |
54 | private static final String TAG = Statistics.class.getCanonicalName();
55 | private static final String
56 | jn_year = "year", jn_month = "month", jn_day = "day",
57 | jn_collected = "collected", jn_helped = "helped", jn_watered = "watered",
58 | jn_answerQuestionList = "answerQuestionList",
59 | jn_questionHint = "questionHint", jn_memberSignIn = "memberSignIn",
60 | jn_exchange = "exchange", jn_kbSignIn = "kbSignIn";
61 |
62 | private TimeStatistics year;
63 | private TimeStatistics month;
64 | private TimeStatistics day;
65 |
66 | // forest
67 | private ArrayList waterFriendLogList;
68 | private ArrayList cooperateWaterList;
69 |
70 | // farm
71 | private ArrayList answerQuestionList;
72 | private String questionHint;
73 | private ArrayList feedFriendLogList;
74 |
75 | // other
76 | private int memberSignIn = 0;
77 | private int exchange = 0;
78 | private int kbSignIn = 0;
79 |
80 | private static Statistics statistics;
81 |
82 | public static void addData(DataType dt, int i)
83 | {
84 | Statistics stat = getStatistics();
85 | resetToday();
86 | switch(dt)
87 | {
88 | case COLLECTED:
89 | stat.day.collected += i;
90 | stat.month.collected += i;
91 | stat.year.collected += i;
92 | break;
93 | case HELPED:
94 | stat.day.helped += i;
95 | stat.month.helped += i;
96 | stat.year.helped += i;
97 | break;
98 | case WATERED:
99 | stat.day.watered += i;
100 | stat.month.watered += i;
101 | stat.year.watered += i;
102 | break;
103 | }
104 | save();
105 | }
106 |
107 | public static int getData(TimeType tt, DataType dt)
108 | {
109 | Statistics stat = getStatistics();
110 | int data = 0;
111 | TimeStatistics ts = null;
112 | switch(tt)
113 | {
114 | case YEAR:
115 | ts = stat.year;
116 | break;
117 | case MONTH:
118 | ts = stat.month;
119 | break;
120 | case DAY:
121 | ts = stat.day;
122 | break;
123 | }
124 | if(ts != null)
125 | switch(dt)
126 | {
127 | case TIME:
128 | data = ts.time;
129 | break;
130 | case COLLECTED:
131 | data = ts.collected;
132 | break;
133 | case HELPED:
134 | data = ts.helped;
135 | break;
136 | case WATERED:
137 | data = ts.watered;
138 | break;
139 | }
140 | return data;
141 | }
142 |
143 | public static String getText()
144 | {
145 | statistics = null;
146 | Statistics stat = getStatistics();
147 | StringBuilder sb = new StringBuilder("year " + getData(TimeType.YEAR, DataType.TIME) + " : collect ");
148 | sb.append(getData(TimeType.YEAR, DataType.COLLECTED));
149 | sb.append(", help " + getData(TimeType.YEAR, DataType.HELPED));
150 | sb.append(", water " + getData(TimeType.YEAR, DataType.WATERED));
151 | sb.append("\nmonth " + getData(TimeType.MONTH, DataType.TIME) + " : collect ");
152 | sb.append(getData(TimeType.MONTH, DataType.COLLECTED));
153 | sb.append(", help " + getData(TimeType.MONTH, DataType.HELPED));
154 | sb.append(", water " + getData(TimeType.MONTH, DataType.WATERED));
155 | sb.append("\nday " + getData(TimeType.DAY, DataType.TIME) + " : collect ");
156 | sb.append(getData(TimeType.DAY, DataType.COLLECTED));
157 | sb.append(", help " + getData(TimeType.DAY, DataType.HELPED));
158 | sb.append(", water " + getData(TimeType.DAY, DataType.WATERED));
159 | if(stat.questionHint != null && !stat.questionHint.isEmpty())
160 | {
161 | sb.append("\nquestion hint : " + stat.questionHint);
162 | }
163 | return sb.toString();
164 | }
165 |
166 | public static boolean canWaterFriendToday(String id, int count)
167 | {
168 | Statistics stat = getStatistics();
169 | int index = -1;
170 | for(int i = 0; i < stat.waterFriendLogList.size(); i++)
171 | if(stat.waterFriendLogList.get(i).userId.equals(id))
172 | {
173 | index = i;
174 | break;
175 | }
176 | if(index < 0) return true;
177 | WaterFriendLog wfl = stat.waterFriendLogList.get(index);
178 | return wfl.waterCount < count;
179 | }
180 |
181 | public static void waterFriendToday(String id, int count)
182 | {
183 | Statistics stat = getStatistics();
184 | WaterFriendLog wfl;
185 | int index = -1;
186 | for(int i = 0; i < stat.waterFriendLogList.size(); i++)
187 | if(stat.waterFriendLogList.get(i).userId.equals(id))
188 | {
189 | index = i;
190 | break;
191 | }
192 | if(index < 0)
193 | {
194 | wfl = stat.new WaterFriendLog(id);
195 | stat.waterFriendLogList.add(wfl);
196 | }else
197 | {
198 | wfl = stat.waterFriendLogList.get(index);
199 | }
200 | wfl.waterCount = count;
201 | save();
202 | }
203 |
204 | public static boolean canCooperateWaterToday(String uid, String coopId)
205 | {
206 | Statistics stat = getStatistics();
207 | return !stat.cooperateWaterList.contains(uid + "_" + coopId);
208 | }
209 |
210 | public static void cooperateWaterToday(String uid, String coopId)
211 | {
212 | Statistics stat = getStatistics();
213 | String v = uid + "_" + coopId;
214 | if(!stat.cooperateWaterList.contains(v))
215 | {
216 | stat.cooperateWaterList.add(v);
217 | save();
218 | }
219 | }
220 |
221 | public static boolean canAnswerQuestionToday(String uid)
222 | {
223 | Statistics stat = getStatistics();
224 | return !stat.answerQuestionList.contains(uid);
225 | }
226 |
227 | public static void answerQuestionToday(String uid)
228 | {
229 | Statistics stat = getStatistics();
230 | if(!stat.answerQuestionList.contains(uid))
231 | {
232 | stat.answerQuestionList.add(uid);
233 | save();
234 | }
235 | }
236 |
237 | public static void setQuestionHint(String s)
238 | {
239 | Statistics stat = getStatistics();
240 | if(stat.questionHint == null)
241 | {
242 | stat.questionHint = s;
243 | save();
244 | }
245 | }
246 |
247 | public static boolean canFeedFriendToday(String id, int count)
248 | {
249 | Statistics stat = getStatistics();
250 | int index = -1;
251 | for(int i = 0; i < stat.feedFriendLogList.size(); i++)
252 | if(stat.feedFriendLogList.get(i).userId.equals(id))
253 | {
254 | index = i;
255 | break;
256 | }
257 | if(index < 0) return true;
258 | FeedFriendLog ffl = stat.feedFriendLogList.get(index);
259 | return ffl.feedCount < count;
260 | }
261 |
262 | public static void feedFriendToday(String id)
263 | {
264 | Statistics stat = getStatistics();
265 | FeedFriendLog ffl;
266 | int index = -1;
267 | for(int i = 0; i < stat.feedFriendLogList.size(); i++)
268 | if(stat.feedFriendLogList.get(i).userId.equals(id))
269 | {
270 | index = i;
271 | break;
272 | }
273 | if(index < 0)
274 | {
275 | ffl = stat.new FeedFriendLog(id);
276 | stat.feedFriendLogList.add(ffl);
277 | }else
278 | {
279 | ffl = stat.feedFriendLogList.get(index);
280 | }
281 | ffl.feedCount++;
282 | save();
283 | }
284 |
285 | public static boolean canMemberSignInToday()
286 | {
287 | Statistics stat = getStatistics();
288 | return stat.memberSignIn < stat.day.time;
289 | }
290 |
291 | public static void memberSignInToday()
292 | {
293 | Statistics stat = getStatistics();
294 | if(stat.memberSignIn != stat.day.time)
295 | {
296 | stat.memberSignIn = stat.day.time;
297 | save();
298 | }
299 | }
300 |
301 | public static boolean canExchangeToday()
302 | {
303 | Statistics stat = getStatistics();
304 | return stat.exchange < stat.day.time;
305 | }
306 |
307 | public static void exchangeToday()
308 | {
309 | Statistics stat = getStatistics();
310 | if(stat.exchange != stat.day.time)
311 | {
312 | stat.exchange = stat.day.time;
313 | save();
314 | }
315 | }
316 |
317 | public static boolean canKbSignInToday()
318 | {
319 | Statistics stat = getStatistics();
320 | return stat.kbSignIn < stat.day.time;
321 | }
322 |
323 | public static void KbSignInToday()
324 | {
325 | Statistics stat = getStatistics();
326 | if(stat.kbSignIn != stat.day.time)
327 | {
328 | stat.kbSignIn = stat.day.time;
329 | save();
330 | }
331 | }
332 |
333 | private static Statistics getStatistics()
334 | {
335 | if(statistics == null)
336 | {
337 | String statJson = null;
338 | if(FileUtils.getStatisticsFile().exists())
339 | statJson = FileUtils.readFromFile(FileUtils.getStatisticsFile());
340 | statistics = json2Statistics(statJson);
341 | }
342 | return statistics;
343 | }
344 |
345 | public static void resetToday()
346 | {
347 | Statistics stat = getStatistics();
348 | String[] dateStr = Log.getFormatDate().split("-");
349 | int ye = Integer.parseInt(dateStr[0]);
350 | int mo = Integer.parseInt(dateStr[1]);
351 | int da = Integer.parseInt(dateStr[2]);
352 |
353 | if(ye > stat.year.time)
354 | {
355 | stat.year.reset(ye);
356 | stat.month.reset(mo);
357 | stat.day.reset(da);
358 | dayClear();
359 | }else if(mo > stat.month.time)
360 | {
361 | stat.month.reset(mo);
362 | stat.day.reset(da);
363 | dayClear();
364 | }else if(da > stat.day.time)
365 | {
366 | stat.day.reset(da);
367 | dayClear();
368 | }
369 | }
370 |
371 | private static void monthClear()
372 | {
373 | }
374 |
375 | private static void dayClear()
376 | {
377 | Statistics stat = getStatistics();
378 | stat.waterFriendLogList.clear();
379 | stat.cooperateWaterList.clear();
380 | stat.answerQuestionList.clear();
381 | stat.feedFriendLogList.clear();
382 | stat.questionHint = null;
383 | stat.memberSignIn = 0;
384 | stat.exchange = 0;
385 | stat.kbSignIn = 0;
386 | save();
387 | FileUtils.getForestLogFile().delete();
388 | FileUtils.getFarmLogFile().delete();
389 | FileUtils.getOtherLogFile().delete();
390 | }
391 |
392 | private static Statistics defInit()
393 | {
394 | Statistics stat = new Statistics();
395 | String[] date = Log.getFormatDate().split("-");
396 | if(stat.year == null)
397 | stat.year = stat.new TimeStatistics(Integer.parseInt(date[0]));
398 | if(stat.month == null)
399 | stat.month = stat.new TimeStatistics(Integer.parseInt(date[1]));
400 | if(stat.day == null)
401 | stat.day = stat.new TimeStatistics(Integer.parseInt(date[2]));
402 | if(stat.cooperateWaterList == null)
403 | stat.cooperateWaterList = new ArrayList<>();
404 | if(stat.answerQuestionList == null)
405 | stat.answerQuestionList = new ArrayList<>();
406 | if(stat.feedFriendLogList == null)
407 | stat.feedFriendLogList = new ArrayList<>();
408 | return stat;
409 | }
410 |
411 | private static Statistics json2Statistics(String json)
412 | {
413 | Statistics stat = null;
414 | try
415 | {
416 | JSONObject jo = new JSONObject(json);
417 | JSONObject joo = null;
418 | stat = new Statistics();
419 |
420 | joo = jo.getJSONObject(jn_year);
421 | stat.year = stat.new TimeStatistics(joo.getInt(jn_year));
422 | Log.i(TAG, jn_year + ":" + stat.year.time);
423 | stat.year.collected = joo.getInt(jn_collected);
424 | Log.i(TAG, " " + jn_collected + ":" + stat.year.collected);
425 | stat.year.helped = joo.getInt(jn_helped);
426 | Log.i(TAG, " " + jn_helped + ":" + stat.year.helped);
427 | stat.year.watered = joo.getInt(jn_watered);
428 | Log.i(TAG, " " + jn_watered + ":" + stat.year.watered);
429 |
430 | joo = jo.getJSONObject(jn_month);
431 | stat.month = stat.new TimeStatistics(joo.getInt(jn_month));
432 | Log.i(TAG, jn_month + ":" + stat.month.time);
433 | stat.month.collected = joo.getInt(jn_collected);
434 | Log.i(TAG, " " + jn_collected + ":" + stat.month.collected);
435 | stat.month.helped = joo.getInt(jn_helped);
436 | Log.i(TAG, " " + jn_helped + ":" + stat.month.helped);
437 | stat.month.watered = joo.getInt(jn_watered);
438 | Log.i(TAG, " " + jn_watered + ":" + stat.month.watered);
439 |
440 | joo = jo.getJSONObject(jn_day);
441 | stat.day = stat.new TimeStatistics(joo.getInt(jn_day));
442 | Log.i(TAG, jn_day + ":" + stat.day.time);
443 | stat.day.collected = joo.getInt(jn_collected);
444 | Log.i(TAG, " " + jn_collected + ":" + stat.day.collected);
445 | stat.day.helped = joo.getInt(jn_helped);
446 | Log.i(TAG, " " + jn_helped + ":" + stat.day.helped);
447 | stat.day.watered = joo.getInt(jn_watered);
448 | Log.i(TAG, " " + jn_watered + ":" + stat.day.watered);
449 |
450 | stat.waterFriendLogList = new ArrayList<>();
451 | Log.i(TAG, Config.jn_waterFriendList + ":[");
452 | if(jo.has(Config.jn_waterFriendList))
453 | {
454 | JSONArray ja = jo.getJSONArray(Config.jn_waterFriendList);
455 | for(int i = 0; i < ja.length(); i++)
456 | {
457 | JSONArray jaa = ja.getJSONArray(i);
458 | WaterFriendLog wfl = stat.new WaterFriendLog(jaa.getString(0));
459 | wfl.waterCount = jaa.getInt(1);
460 | stat.waterFriendLogList.add(wfl);
461 | Log.i(TAG, " " + wfl.userId + "," + wfl.waterCount + ",");
462 | }
463 | }
464 |
465 | stat.cooperateWaterList = new ArrayList<>();
466 | Log.i(TAG, Config.jn_cooperateWaterList + ":[");
467 | if(jo.has(Config.jn_cooperateWaterList))
468 | {
469 | JSONArray ja = jo.getJSONArray(Config.jn_cooperateWaterList);
470 | for(int i = 0; i < ja.length(); i++)
471 | {
472 | stat.cooperateWaterList.add(ja.getString(i));
473 | Log.i(TAG, stat.cooperateWaterList.get(i) + ",");
474 | }
475 | }
476 |
477 | stat.answerQuestionList = new ArrayList<>();
478 | Log.i(TAG, jn_answerQuestionList + ":[");
479 | if(jo.has(jn_answerQuestionList))
480 | {
481 | JSONArray ja = jo.getJSONArray(jn_answerQuestionList);
482 | for(int i = 0; i < ja.length(); i++)
483 | {
484 | stat.answerQuestionList.add(ja.getString(i));
485 | Log.i(TAG, stat.answerQuestionList.get(i) + ",");
486 | }
487 | }
488 |
489 | if(jo.has(jn_questionHint))
490 | stat.questionHint = jo.getString(jn_questionHint);
491 | Log.i(TAG, jn_questionHint + ":" + stat.questionHint);
492 |
493 | stat.feedFriendLogList = new ArrayList<>();
494 | Log.i(TAG, Config.jn_feedFriendAnimalList + ":[");
495 | if(jo.has(Config.jn_feedFriendAnimalList))
496 | {
497 | JSONArray ja = jo.getJSONArray(Config.jn_feedFriendAnimalList);
498 | for(int i = 0; i < ja.length(); i++)
499 | {
500 | JSONArray jaa = ja.getJSONArray(i);
501 | FeedFriendLog ffl = stat.new FeedFriendLog(jaa.getString(0));
502 | ffl.feedCount = jaa.getInt(1);
503 | stat.feedFriendLogList.add(ffl);
504 | Log.i(TAG, " " + ffl.userId + "," + ffl.feedCount + ",");
505 | }
506 | }
507 |
508 | if(jo.has(jn_memberSignIn))
509 | stat.memberSignIn = jo.getInt(jn_memberSignIn);
510 | Log.i(TAG, jn_memberSignIn + ":" + stat.memberSignIn);
511 |
512 | if(jo.has(jn_exchange))
513 | stat.exchange = jo.getInt(jn_exchange);
514 | Log.i(TAG, jn_exchange + ":" + stat.exchange);
515 |
516 | if(jo.has(jn_kbSignIn))
517 | stat.kbSignIn = jo.getInt(jn_kbSignIn);
518 | Log.i(TAG, jn_kbSignIn + ":" + stat.kbSignIn);
519 |
520 | }catch(Throwable t)
521 | {
522 | Log.printStackTrace(TAG, t);
523 | if(json != null)
524 | {
525 | Log.i(TAG, "统计文件格式有误,已重置统计文件并备份原文件");
526 | FileUtils.write2File(json, FileUtils.getBackupFile(FileUtils.getStatisticsFile()));
527 | }
528 | stat = defInit();
529 | }
530 | String formated = statistics2Json(stat);
531 | if(!formated.equals(json))
532 | {
533 | Log.i(TAG, "重新格式化 statistics.json");
534 | FileUtils.write2File(formated, FileUtils.getStatisticsFile());
535 | }
536 | return stat;
537 | }
538 |
539 | private static String statistics2Json(Statistics stat)
540 | {
541 | JSONObject jo = new JSONObject();
542 | JSONArray ja = null;
543 | try
544 | {
545 | if(stat == null) stat = Statistics.defInit();
546 | JSONObject joo = new JSONObject();
547 | joo.put(jn_year, stat.year.time);
548 | joo.put(jn_collected, stat.year.collected);
549 | joo.put(jn_helped, stat.year.helped);
550 | joo.put(jn_watered, stat.year.watered);
551 | jo.put(jn_year, joo);
552 |
553 | joo = new JSONObject();
554 | joo.put(jn_month, stat.month.time);
555 | joo.put(jn_collected, stat.month.collected);
556 | joo.put(jn_helped, stat.month.helped);
557 | joo.put(jn_watered, stat.month.watered);
558 | jo.put(jn_month, joo);
559 |
560 | joo = new JSONObject();
561 | joo.put(jn_day, stat.day.time);
562 | joo.put(jn_collected, stat.day.collected);
563 | joo.put(jn_helped, stat.day.helped);
564 | joo.put(jn_watered, stat.day.watered);
565 | jo.put(jn_day, joo);
566 |
567 | ja = new JSONArray();
568 | for(int i = 0; i < stat.waterFriendLogList.size(); i++)
569 | {
570 | WaterFriendLog wfl = stat.waterFriendLogList.get(i);
571 | JSONArray jaa = new JSONArray();
572 | jaa.put(wfl.userId);
573 | jaa.put(wfl.waterCount);
574 | ja.put(jaa);
575 | }
576 | jo.put(Config.jn_waterFriendList, ja);
577 |
578 | ja = new JSONArray();
579 | for(int i = 0; i < stat.cooperateWaterList.size(); i++)
580 | {
581 | ja.put(stat.cooperateWaterList.get(i));
582 | }
583 | jo.put(Config.jn_cooperateWaterList, ja);
584 |
585 | ja = new JSONArray();
586 | for(int i = 0; i < stat.answerQuestionList.size(); i++)
587 | {
588 | ja.put(stat.answerQuestionList.get(i));
589 | }
590 | jo.put(jn_answerQuestionList, ja);
591 |
592 | if(stat.questionHint != null)
593 | jo.put(jn_questionHint, stat.questionHint);
594 |
595 | ja = new JSONArray();
596 | for(int i = 0; i < stat.feedFriendLogList.size(); i++)
597 | {
598 | FeedFriendLog ffl = stat.feedFriendLogList.get(i);
599 | JSONArray jaa = new JSONArray();
600 | jaa.put(ffl.userId);
601 | jaa.put(ffl.feedCount);
602 | ja.put(jaa);
603 | }
604 | jo.put(Config.jn_feedFriendAnimalList, ja);
605 |
606 | jo.put(jn_memberSignIn, stat.memberSignIn);
607 |
608 | jo.put(jn_exchange, stat.exchange);
609 |
610 | jo.put(jn_kbSignIn, stat.kbSignIn);
611 | }catch(Throwable t)
612 | {
613 | Log.printStackTrace(TAG, t);
614 | }
615 | return Config.formatJson(jo, false);
616 | }
617 |
618 | private static boolean save()
619 | {
620 | return FileUtils.write2File(statistics2Json(getStatistics()), FileUtils.getStatisticsFile());
621 | }
622 |
623 | }
624 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
10 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_html_viewer.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
23 |
24 |
33 |
34 |
43 |
44 |
53 |
54 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/dialog_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
20 |
21 |
27 |
28 |
38 |
39 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/include_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
29 |
30 |
37 |
38 |
45 |
46 |
53 |
54 |
61 |
62 |
63 |
64 |
68 |
69 |
76 |
77 |
84 |
85 |
97 |
98 |
110 |
111 |
123 |
124 |
136 |
137 |
149 |
150 |
162 |
163 |
175 |
176 |
188 |
189 |
196 |
197 |
209 |
210 |
222 |
223 |
230 |
231 |
243 |
244 |
251 |
252 |
264 |
265 |
266 |
267 |
271 |
272 |
279 |
280 |
287 |
288 |
295 |
296 |
303 |
304 |
316 |
317 |
329 |
330 |
342 |
343 |
350 |
351 |
358 |
359 |
366 |
367 |
374 |
375 |
382 |
383 |
390 |
391 |
398 |
399 |
406 |
407 |
419 |
420 |
427 |
428 |
440 |
441 |
442 |
443 |
447 |
448 |
455 |
456 |
463 |
464 |
471 |
472 |
479 |
480 |
492 |
493 |
505 |
506 |
513 |
514 |
515 |
516 |
520 |
521 |
528 |
529 |
541 |
542 |
543 |
544 |
545 |
546 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - 生活不可能像你想象得那么好,但也不会像你想象得那么糟。我觉得人的脆弱和坚强都超乎自己的想象。有时,我可能脆弱得一句话就泪流满面;有时,也发现自己咬着牙走了很长的路。
7 | - 人生就像一杯茶,不会苦一辈子,但总会苦一阵子。
8 | - 你坚持下来了,而别人坚持不下来,这就是你的资本。
9 | - 生活有苦有甜,才叫完整。日子有阴有晴,才叫自然。心情有悲有喜,才叫体会。爱情有闹有和,才叫情趣。
10 | - 君子的力量永远是行动的力量,而不是语言的力量。
11 | - 人生寂寞是一种力量。人经得起寂寞,就能获得自由;耐不住寂寞,就会受人牵制。
12 | - 茶不过两种姿态,浮、沉;饮茶人不过两种姿势,拿起、放下。人生如茶,沉时坦然,浮时淡然,拿得起也需要放得下。
13 | - 我相信,无论今后的道路多么坎坷,只要抓住今天,迟早会在奋斗中尝到人生的甘甜。抓住人生中的一分一秒,胜过虚度中的一月一年!
14 | - 生活就像是一盘巧克力,你永远不知道会碰到什么味道。
15 | - 失去认认真真的第一次爱后,男人可能不会再那样对女孩子真正好了,没有心劲,没有激情,没有对浪漫爱情的信仰了!有些事,一辈子只有一次!
16 | - 每个人都有自己的泪要擦,每个人都有自己的路要走,只要记得:冷了,给自己加件外衣;饿了,给自己买个面包;痛了,给自己一份坚强;失败了,给自己一个目标;跌倒了,在伤痛中爬起,给自己一个宽容的微笑继续往前走,已足够!不必仰望别人,自己亦是风景。
17 | - 宁愿因做自己而招人厌恶,也不愿为了迎合他人而伪装自己,懂你的人会留下来,不懂你的人,你祈求不来。因为别人活得不快乐,不如为了自己活得更自由。
18 | - 多数的错失,是因为不坚持,不努力,不挽留,然后催眠自己说一切都是命运。
19 | - 世界上最远的距离,不是爱,不是恨,而是熟悉的人,渐渐变得陌生。
20 | - 真正的坚韧,应该是哭的时候要彻底,笑的时候要开怀,说的时候要淋漓尽致,做的时候要毫不犹豫。
21 | - 有时候,没有下一次,没有机会重来,没有暂停继续。有时候,错过了现在,就永远永远的没机会了。
22 | - 能救你脱出苦海的只有你自己。让自己变得更好,才是唯一的出路。
23 | - 有多少人以友谊的名义,爱着一个人,认为拥有,就是失去的开始。
24 | - 如果有一天,让你心动的再也感动不了你,让你愤怒的再也激怒不了你,让你悲伤的再也不能让你流泪,你便知道这时光,这生活给了你什么,你为了成长,付出了什么。
25 | - 身健如山,心静似水,淡泊名利。这是人生最高境界,谁能活得如此境界,谁的一生就活得自在。
26 | - 此生,若作浮萍,随波逐流任汝摧;若为斗士,披荆斩棘腰不折。此生非彼生,此时非彼时。不争五斗米,不作无根萍。
27 | - 所有的努力,不是为了让别人觉得你了不起,而是为了能让自己打心眼里看得起自己。
28 | - 努力和收获,都是自己的,与他人无关。最大的成就感,就是一直在朝着自己想要的方向前进。
29 | - 誓言是世界上最靠不住的东西,只有你对别人还有用的时候,别人才会遵守誓言。
30 | - 许多不管怎么做、怎么想都没结果的事,要懂得交给时间。有些事,无论你怎么努力,怎么勉强,时间不够,还是耐心的等待吧。
31 | - 别因为落入了一把牛毛就把一锅奶油泼掉,别因为犯了一点错误就把一生的事业扔掉。
32 | - 成年人的世界,似乎只有赚到足够的钱,才能过上简单、安逸、自由的生活,才能让自己活得更有底气些。所以,多一些努力吧,少点功夫矫情。
33 | - 人生最困难的时候,也许正是转变的时候:改变固有的思想,人生就可能迎来转机。幸运,总是离努力的人更近一些。
34 | - 人生幸福三诀:不要拿自己的错误来惩罚自己;不要拿自己的错误来惩罚别人;不要拿别人的错误来惩罚自己。有了这三条,人生就不会太累了。
35 | - 如果你要做一件事,不要到处宣言自己的想法,只管安安静静地去做,值不值,时间是最好的证明,自己的人生,得自己负责。
36 | - 一定要真诚地认真地度过人生每一天。不要再轻易抱怨人生苦短,其实所有美丽的风景都在自己的心里和手上,与其抱怨明天不是那么如意,不如把今天的手头事做好。
37 | - 你过得太闲,才有时间执着在无意义的事情上,才有时间无病呻吟所谓痛苦。你看那些忙碌的人,他们的时间都花在努力上。
38 | - 努力去做一个温暖的人,用真心对世界微笑,用眼泪提醒自己要做的更好,用快乐去迎接每一天的阳光,用自信向世界宣称你过得很好。
39 | - 很多时候不是命运的不幸,而是自己还不够努力。你越积极乐观、越是勇敢面对,好运就会来到。
40 | - 生命中最悲哀的一件事,就是遇到了一个对你来说很重要的人,但你却到了最后才发现,一切都太迟了,你无力回天,只好任其随风而逝。
41 | - 让自己一边成熟,一边寻找时机。等时机成熟时,理想就可以实现了。如果你的面前有阴影,那是因为你的背后有阳光。
42 | - 不想认命,就去拼命。我始终相信,付出就会有收获,或大或小,或迟或早,始终不会辜负你的努力。有一种落差是,你总是羡慕别人的成功,自己却不敢开始。
43 | - 真正成功的人生,不在于成就的大小,而在于你是否努力地去实现自我,喊出自己的声音,走出属于自己的道路。
44 | - 和那些比你有钱,比你优秀,比你有能力,还比你努力的人做朋友是很有压力的。跟他们在一起,你不努力都会不好意思。如果你方圆一里内都没有一个励志的人,那么你就要考虑换一个环境了。
45 | - 当你的才华还撑不起你的野心时,那你就应该静下心来学习。当你的经济还撑不起你的梦想时,那你就应该踏实的去工作!
46 | - “我很好”不是指你终于熬到有了钱,有了朋友,有了人照顾的日子。而是你终于可以习惯没有钱,没有朋友,没有人照顾的日子。“我很好”是告诉他们,你越来越能接受现实,而不是越来越现实。
47 | - 负面情绪就像黑暗无法驱赶,唯一能做的,就是带进光里。
48 | - 只有内心平和淡定的人,才能看到沿途的风景,看到洒落在窗台上的点点阳光。
49 | - 当一个人学会与自己和解的时候,那些曾经的纠结、过往的苦难,都会转化成前行的强大力量,支撑你走向豁达…
50 | - 当面赞扬,不一定是别人的真实想法,而是时局需要。
51 | - 一个人要知道自己的位置,就像一个人知道自己的脸面一样,这是最为清醒的自觉。洗尽铅华总是比随意的涂脂抹粉来得美。所以做能做的事,把它做的最好,这才是做人的重要。
52 | - 愿意放弃才不会苦,适度知足才不会悔;记住感恩才不会怨,懂得珍惜才不会愧。人生,在心淡中求满足,在尽责中求心安,在奉献中求快乐,在忠诚中求幸福。
53 | - 当你无助时,你可以哭,但哭过你必须要振作起来,绝地逢生并不罕见,何况不是绝境!
54 | - 坚持是一种可贵的品质,但是如果坚持了错的方向,那么勇于放下、改变也是一种智慧!
55 | - 一个人的快乐不是因为他拥有的多而是因为他计较的少。
56 | - 小时候觉得这个世界不公平,后来发现这个世界就是不公平,但这些不公平让你更努力。
57 | - 光阴可以消磨我们的风华,却带给我们成熟的魅力;风尘能够暗淡我们的容颜,却将一份智慧与淡定浸润在我们的心灵。
58 | - 世界原本就不是属于你,因此你用不着抛弃,要抛弃的是一切的执著。
59 | - 与其热闹着引人夺目,步步紧逼,不如趋向做一个人群中真实自然的人,不张扬,不虚饰,随时保持退后的位置。心有所定,只是专注做事。
60 | - 如果你生气了,请在面对别人之前先面对镜子。看看自己,你喜欢现在这张脸吗?
61 | - 我似乎听到了一句话,一句曾经我对别人说过的话,我感受到了曾经听到这句话的人的感受。也许你今后也会听到这样一句话,一句你曾经对别人说过的话,而到那个时候,你就会感受到当时听你说这句话的那个人的感受。
62 | - 好听的音乐不应该天天都听,因为听的次数太多会倦腻。
63 | - 生活很苦,但要学会苦中作乐。
64 | - 谎言不会伤人,真相才是快刀。
65 | - 合适的话语,胜过锋利的刀子。
66 | - 自立自主,总胜过俯首为奴。
67 | - 值得做的事情,就是值得做对的事情。
68 | - 不要被骄傲,遮蔽了双眼。
69 | - 真正的大师,永远都怀着一颗学徒的心。
70 | - 吾虽浪迹天涯,却未迷失本心。
71 | - 每一张牌,都是对你的一份思念,我赌赢了所有,却赢不回你的爱。
72 | - 一曲终了,繁花散尽,伊人已逝,只余一声空叹。
73 | - 纵然前途迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻止我寻找你的道路。
74 | - 当黑色的玫瑰悄悄绽放,除了镜花水月,又有谁能了解我的心。
75 | - 恶人终有恶报,为了那些不能作战的人而战。
76 | - 无论刮风还是下雨,太阳照常升起。
77 | - 有时候,你需要亲手打开一扇门。
78 | - 不要错把仁慈当作弱小。
79 | - 即使一无所有,也要未雨绸缪。
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | XQuickEnergy
5 | Hello User!
6 |
7 | #00000000
8 | #F0F0F0
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
--------------------------------------------------------------------------------
/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.+'
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 | }
19 | }
20 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------