Repository: zhongyi-tong/WeChatLuckyMoney
Branch: stable
Commit: 54a5201dfba6
Files: 59
Total size: 124.4 KB
Directory structure:
gitextract_2tar33oo/
├── .gitignore
├── .idea/
│ ├── compiler.xml
│ ├── copyright/
│ │ └── profiles_settings.xml
│ ├── encodings.xml
│ ├── gradle.xml
│ ├── inspectionProfiles/
│ │ └── Project_Default.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── runConfigurations.xml
│ ├── uiDesigner.xml
│ └── vcs.xml
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── README_EN.md
├── WeChatLuckyMoney.iml
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ ├── java/
│ │ └── xyz/
│ │ └── monkeytong/
│ │ └── hongbao/
│ │ ├── activities/
│ │ │ ├── MainActivity.java
│ │ │ ├── SeekBarPreference.java
│ │ │ ├── SettingsActivity.java
│ │ │ └── WebViewActivity.java
│ │ ├── fragments/
│ │ │ ├── CommentSettingsFragment.java
│ │ │ └── GeneralSettingsFragment.java
│ │ ├── services/
│ │ │ └── HongbaoService.java
│ │ └── utils/
│ │ ├── ConnectivityUtil.java
│ │ ├── DownloadUtil.java
│ │ ├── HongbaoLogger.java
│ │ ├── HongbaoSignature.java
│ │ ├── PowerUtil.java
│ │ └── UpdateTask.java
│ └── res/
│ ├── layout/
│ │ ├── activity_main.xml
│ │ ├── activity_preferences.xml
│ │ ├── activity_webview.xml
│ │ ├── preference_category.xml
│ │ ├── preference_checkbox.xml
│ │ └── preference_seekbar.xml
│ ├── layout-v21/
│ │ ├── activity_preferences.xml
│ │ └── activity_webview.xml
│ ├── values/
│ │ ├── dimens.xml
│ │ └── strings.xml
│ ├── values-en/
│ │ └── strings.xml
│ ├── values-w820dp/
│ │ ├── dimens.xml
│ │ └── strings.xml
│ └── xml/
│ ├── accessible_service_config.xml
│ ├── comment_preferences.xml
│ ├── general_preferences.xml
│ └── provider_paths.xml
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── monkeytong.jks.enc
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.imi
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
/.idea/dictionaries
/monkeytong.jks
/app/release
================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
================================================
FILE: .idea/copyright/profiles_settings.xml
================================================
<component name="CopyrightManager">
<settings default="" />
</component>
================================================
FILE: .idea/encodings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
================================================
FILE: .idea/gradle.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
<option name="gradleJvm" value="1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
================================================
FILE: .idea/inspectionProfiles/Project_Default.xml
================================================
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidLintSetTextI18n" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/WeChatLuckyMoney.iml" filepath="$PROJECT_DIR$/WeChatLuckyMoney.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>
================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
================================================
FILE: .idea/uiDesigner.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
================================================
FILE: .travis.yml
================================================
language: android
sudo: false
jdk: oraclejdk8
env:
matrix:
- ANDROID_TARGET=android-26 ANDROID_ABI=armeabi-v7a armeabi
android:
components:
- platform-tools
- tools
- build-tools-26.0.2
- android-N
- extra
licenses:
- android-sdk-license-.+
- .+
before_install:
- openssl aes-256-cbc -K $encrypted_6b42a8524af0_key -iv $encrypted_6b42a8524af0_iv
-in monkeytong.jks.enc -out monkeytong.jks -d
before_script:
- mkdir "$ANDROID_HOME/licenses" || true
- echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"
- echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
- gem install fir-cli
script:
- ./gradlew assembleRelease
deploy:
provider: releases
api_key:
secure: Ookr5Qba+FjvrnlHfA2Gp+9QSua/UhkAq+OtYtLagdC7i1Drd7CANi4zfhCf95xSPDNE8MNJQu2qTR4EkHqno6dBFYbV/+35Ph+3Xnv1GehJmdyVDQSfNwlxzKbCw6rfyoeiMrSORADznRlEx7EfK3b7w2esWS/OAvepbqmUzWlPEA8Xyl1CBiMZacqZJTwyhCCO5dNpXE/+pP4yPrUx32Ts0tYQ5HmsijndbWh/YX2SGeekdAWTXBMr/zUpTEcpk8JYukfuTG3qaNZnUk0OEYHv8/icdaTO+wUuj44m9y/0uoir7iToAjEQP+tEnfUAQYke5Di2N2Pa9dpuc2kvmHi2l4wpPDhwrSSAPkI73r1eM8AAl7U2d2G/qG7UGAmXoI4NnDozkCGrHDH4VLH/uSpoJPdsVSOPRZX7lWPIM6xBoz+3AW0mtZbRsduvwvqR24B/xEs9jy02RJin3VQw1qlVYATUvThrNqMUz45AgVvjx00llX6i5As7xkWwLjZSEpr6FWEjOtPg1ZHWBxD/dCHWpcL7nnGAWi2INTUT6NgN9ZpuU0tgHMMMx/7bfUM1EVEpJKjKLyaX8XmsRmztPUYOhRN/m2uEoiiOu54QoD9oszszIlEqT5jneu8LQ1Ie9ICaGF1Mj2CgbWB0hTvKSTPTP1hXF0FHtwmaTDwKKVE=
file: app/build/outputs/apk/app-release.apk
skip_cleanup: true
on:
repo: geeeeeeeeek/WeChatLuckyMoney
branch: stable
tags: true
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/d83cc8365de0abdd097e
on_success: always
on_failure: always
on_start: always
================================================
FILE: CHANGELOG.md
================================================
# 更新日志
**[v4.0 (2017.01.27)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v4.0)**
- 新年快乐!
- 新增 多语言支持,目前支持中文和英文两种语言
- 新增 适配部分Android 7.0机型(进行中,华为等部分机型仍不可用)
- 优化 UI
- 优化 性能改进
- 修复 Uber与滴滴合并后优惠链接失效的问题
- 修复 Bugly高优先级的问题
- 移除 自动回复功能
**[v3.0 (2016.08.02)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v3.0.1)**
- 优化 重新设计UI,风格更加简洁明快。提升“社区”和“设置”的视觉优先级,开启插件更顺手。
- 新增 Uber免费乘车优惠。
- 新增 适配微信6.3.22。
- 新增 Android N (牛轧糖) 适配(预计v3.1完成)
- 修复 Bugly高优先级的问题。
**[v2.3 (2016.02.07)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v2.3)**
- 优化 不打开拜年红包
- 紧急修复了Bugly上几个高优先级的问题,减少Crash出现
**[v2.2 (2016.02.04)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v2.2)**
- 新增 延时拆开红包的可选项
- 新增 跳转至浏览器打开的入口
- 新增 接入腾讯Bugly
- 新增 自动回复的可选项(实验中)
- 优化 手动拆开的红包不返回
- 优化 适配三星等坑爹机型 (感谢 [@firesunCN](https://github.com/firesunCN) 对这项修改的贡献)
- 修复 拆开红包后的多次返回问题
**[v2.1 (2016.01.30)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v2.1.1)**
- 新增 屏蔽指定红包文字的可选项
- 新增 息屏抢红包的可选项
- 新增 不拆开自己发的红包的可选项
- 新增 内置红包攻略
- 新增 所有链接默认用内置WebView打开
- 优化 仅在WiFi环境下回到应用时检测更新
- 优化 抢红包的逻辑流程,减少了一些误判情形
- 优化 适配了Lollipop以上版本的透明Status Bar
- 修复 插件开启后按钮仍然显示“开启插件”
- 修复 监听SharedPreferences变化无效的问题 (感谢 @act262 对这项修改的贡献)
- 修复 在其他界面会做额外的操作的问题 (感谢 @sxyy 对这项修改的贡献)
- 修复 响应Notification进入聊天后,可能误判不抢的问题 (感谢 @tttony3 对这项修改的贡献)
**[v2.0.1 (2016.01.23)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v2.0.1)**
- 修复了用户第一次使用,偏好设置未加载导致的插件失效。 Fix issue #50, #51.
**[v2.0 (2016.01.23)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v2.0)**
- 更自由的监视选项. Give user the freedom to choose what to watch, chat/list/notifications available at choices.
- 更优化的重复红包判定. Optimize algorithm for duplicate hongbao detection.
- 自动更新机制. Add auto update module.
- 更新UI设计、应用图标. Update UI and app icon.
- 增加辅助服务的说明. Add description for accessibility service.
- 增加了反馈issue的快捷方式. Add quick link to Github issues.
- 替换包名. Substitute the original package name.
详细的release notes请见https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues/48。
**[v1.4 (2016.01.16)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1.4)**
- 修复了微信新版(6.3.9.48_refecd3e)红包UI调整导致的功能失效。Fix failure caused by new WeChat Hongbao UI. Related issue #41.
**[v1.3 (2015.12.29)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1.3)**
- 修复了红包频繁点击的bug。Fix repeatedly opening envelopes. Related issue #27 .
- 并入了从通知栏进入抢红包的代码(#28),充分测试后加入下一个版本。Add watch for WeChat notification, from which enter the chat activity. This feature will not be available in this version, until well tested.
**[v1.2 (2015.12.17)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1.2)**
该版本的红包识别代码存在Bug,会出现频繁点击,建议跳过该版本。
- 增加了微信语言 英语 的支持,修复了由此导致的一系列问题. Add support for the English language. Fix related issues.
- 修改了红包重复判断的逻辑,戳“名称与缓存不一致的红包”和“名称一致且间隔大于5秒”的红包。Change the logic of detecting duplicate red envelopes. Only those name unmatched with cached or those name matched but with a duration > 5 secs will be touched.
**[v1.1 (2015.10.28)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1.1)**
- 服务运行时防止息屏。Keep screen on when service is running.
**[v1.0 (2015.10.07)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1.0)**
- 从dev分支并入了新版UI和红包节点的hash算法。
- 增加了红包重复判断,不再不停点击最新的红包,极大优化了性能和体验。
**[Preview (2015.08.17)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v1-beta1)**
- 对源码进行了少量修改。
================================================
FILE: LICENSE.md
================================================
**The MIT License (MIT)**
Copyright (c) 2016 Zhongyi Tong ([geeeeeeeeek@Github](https://github.com/geeeeeeeeek))
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# 微信红包
[](https://gitter.im/geeeeeeeeek/WeChatLuckyMoney?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [](https://travis-ci.org/geeeeeeeeek/WeChatLuckyMoney) [](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/README_EN.md)
一个帮助你在微信抢红包时战无不胜的Android应用。自动检测并且拆开红包,速度超乎你的想象。
支持中英文。前往[**Release**](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/)下载最新版本。已下载用户可直接在设置里面更新。
### 特性
- **监视选项任意组合,满足多样化的使用需求**[[?]](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues/48)
提供了`系统通知`/`聊天列表`/`聊天页面`三档选项,无论是想要谨慎不被察觉,还是想要高效志在必得,这个插件如你所愿。
- **不仅快人一步,红包识别更加智能**
多种特征标识,聊天时不再重复点击红包。智能过滤红包关键字[[?]](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues/97),避免落入“专属红包”、“抢到翻倍”的陷阱。还可以设置延时抢红包和自动回复感谢语[[?]](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues/118)。
- **紧跟微信更新**
第一时间适配最新版本微信,应用内即可一键更新。
- **轻量、安全、值得信赖**
安装包仅1M,无需ROOT,下载即用。代码公开透明,活跃的社区讨论,数万用户下载,值得你的信赖。
### 使用方法
1. 打开『微信红包』应用,开启插件。
2. 做你想做的事。
3. 坐等红包进账。
### 实现原理
请见[技术文档](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/dev/README.md),注意文档描述的是dev分支(已弃用)的具体实现,而不是stable分支。若有疑问,请在[ISSUES](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues)中提出。
### 更新日志
完整的更新日志请见[CHANGELOG](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/CHANGELOG.md)。
### **版权及免责声明**
本项目源自小米去年秋季发布会时演示的MIUI 7抢红包测试[代码](https://github.com/XiaoMi/LuckyMoneyTool)。
插件可能会在一定程度上改变微信的交互方式。使用本项目中包含的代码及其生成物时,使用者自行承担随之而来的各种风险,包括但不限于“禁用红包功能”、“微信封号”。
本项目使用[MIT许可证](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/LICENSE.md)。
### 应用截图


================================================
FILE: README_EN.md
================================================
# WeChat Lucky Money
[](https://gitter.im/geeeeeeeeek/WeChatLuckyMoney?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [](https://travis-ci.org/geeeeeeeeek/WeChatLuckyMoney) [](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/README.md)
This Android app helps you snatch red envelopes in WeChat. It detects red envelopes automatically, and clicks to open them faster than your imagination.
Available in English and Chinese. Please goto the [**Release**](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/) page to download the latest version.
### Spotlights
- **What to watch is at your choice**[[?]](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues/48)
Three levels of watch options: `notification`/`chat list`/`chat page`. Whatever a coutious man or an ambitious one you wanna be, the choice is at yours.
- **More intelligent algorithm**
Multiple features used to identify a red envelope. No more repeated clickings. Anti-anti-plugin strategies are protecting the app from disability.
- **Auto update checking**
Work with the latest version of WeChat. Update available inside your app.
- **Light, safe, and trustful**
Tha package is as light as 1Mb. With code open sourced, active community discussions, tens of thousands of downloads, it's worth your trust.
### How to use
1. Open the app, turn on the service.
2. Do whatever you wanna do.
3. Wait for the lucky money comes in your pocket.
### Implementation
See the [document](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/dev/README.md), which is targeted at the dev branch (deprecated) and is IN CHINESE. If it bothers you, leave your message in the [ISSUES](https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues).
### Update history
For full history, see [CHANGELOG](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/CHANGELOG.md).
### License
The project was heavily inspired by the [app](https://github.com/XiaoMi/LuckyMoneyTool) demonstrated on XiaoMi's news conference for its phone product last autumn.
This app might alter the natural way of interactions with WeChat. When you are using the code and its accessories, you are fully responsible for any possible consequences.
The project is licensed to the [MIT](https://github.com/geeeeeeeeek/WeChatLuckyMoney/blob/stable/LICENSE.md).
### Snapshots


================================================
FILE: WeChatLuckyMoney.iml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="WeChatLuckyMoney" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
================================================
FILE: app/.gitignore
================================================
# Built application files
*.apk
*.ap_
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# Intellij
*.iml
.idea/
# Keystore files
*.jks
================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "26.0.2"
useLibrary 'org.apache.http.legacy'
defaultConfig {
applicationId "xyz.monkeytong.hongbao"
minSdkVersion 19
targetSdkVersion 25
versionCode 7
versionName "v5.0.0"
ndk {
//设置支持的SO库架构
abiFilters 'armeabi', 'armeabi-v7a' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
}
signingConfigs {
releaseConfig {
storeFile file("../monkeytong.jks")
storePassword project.hasProperty("KEYSTORE_PASS") ? KEYSTORE_PASS : System.getenv("KEYSTORE_PASS")
keyAlias project.hasProperty("ALIAS_NAME") ? ALIAS_NAME : System.getenv("ALIAS_NAME")
keyPassword project.hasProperty("ALIAS_PASS") ? ALIAS_PASS : System.getenv("ALIAS_PASS")
}
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.releaseConfig
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.tencent.bugly:crashreport_upgrade:latest.release'
//其中latest.release指代最新版本号,也可以指定明确的版本号,例如1.0.1
compile 'com.tencent.bugly:nativecrashreport:latest.release'
//其中latest.release指代最新版本号,也可以指定明确的版本号,例如2.2.0
compile 'com.android.support:support-v4:25.4.0'
compile 'com.android.support:appcompat-v7:25.4.0'
}
================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/nian/Android/Sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
-keep class android.support.**{*;}
================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xyz.monkeytong.hongbao">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".activities.MainActivity"
android:label="@string/app_name"
android:theme="@style/Base.Theme.AppCompat.Light"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".activities.SettingsActivity"
android:theme="@style/Base.Theme.AppCompat.Light"
android:launchMode="standard">
</activity>
<activity android:name=".activities.WebViewActivity"
android:theme="@style/Base.Theme.AppCompat.Light"
android:launchMode="standard">
</activity>
<activity
android:name="com.tencent.bugly.beta.ui.BetaActivity"
android:theme="@android:style/Theme.Translucent" />
<service
android:name=".services.HongbaoService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data android:name="android.accessibilityservice"
android:resource="@xml/accessible_service_config"/>
</service>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="xyz.monkeytong.hongbao.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>
</manifest>
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/MainActivity.java
================================================
package xyz.monkeytong.hongbao.activities;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.tencent.bugly.Bugly;
import xyz.monkeytong.hongbao.R;
import xyz.monkeytong.hongbao.utils.ConnectivityUtil;
import xyz.monkeytong.hongbao.utils.UpdateTask;
import java.util.List;
public class MainActivity extends Activity implements AccessibilityManager.AccessibilityStateChangeListener {
//开关切换按钮
private TextView pluginStatusText;
private ImageView pluginStatusIcon;
//AccessibilityService 管理
private AccessibilityManager accessibilityManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//CrashReport.initCrashReport(getApplicationContext(), "900019352", false);
Bugly.init(getApplicationContext(), "900019352", false);
setContentView(R.layout.activity_main);
pluginStatusText = (TextView) findViewById(R.id.layout_control_accessibility_text);
pluginStatusIcon = (ImageView) findViewById(R.id.layout_control_accessibility_icon);
handleMaterialStatusBar();
explicitlyLoadPreferences();
//监听AccessibilityService 变化
accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
accessibilityManager.addAccessibilityStateChangeListener(this);
updateServiceStatus();
}
private void explicitlyLoadPreferences() {
PreferenceManager.setDefaultValues(this, R.xml.general_preferences, false);
}
/**
* 适配MIUI沉浸状态栏
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void handleMaterialStatusBar() {
// Not supported in APK level lower than 21
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
Window window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0xffE46C62);
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
updateServiceStatus();
// Check for update when WIFI is connected or on first time.
if (ConnectivityUtil.isWifi(this) || UpdateTask.count == 0)
new UpdateTask(this, false).update();
}
@Override
protected void onDestroy() {
//移除监听服务
accessibilityManager.removeAccessibilityStateChangeListener(this);
super.onDestroy();
}
public void openAccessibility(View view) {
try {
Toast.makeText(this, getString(R.string.turn_on_toast) + pluginStatusText.getText(), Toast.LENGTH_SHORT).show();
Intent accessibleIntent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(accessibleIntent);
} catch (Exception e) {
Toast.makeText(this, getString(R.string.turn_on_error_toast), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
public void openGitHub(View view) {
Intent webViewIntent = new Intent(this, WebViewActivity.class);
webViewIntent.putExtra("title", getString(R.string.webview_github_title));
webViewIntent.putExtra("url", "https://github.com/geeeeeeeeek/WeChatLuckyMoney");
startActivity(webViewIntent);
}
public void openUber(View view) {
Intent webViewIntent = new Intent(this, WebViewActivity.class);
webViewIntent.putExtra("title", getString(R.string.webview_alipay_title));
String[] couponList = new String[]{"https://render.alipay.com/p/f/fd-j6lzqrgm/guiderofmklvtvw.html?shareId=2088422430692204&campStr=p1j%2BdzkZl018zOczaHT4Z5CLdPVCgrEXq89JsWOx1gdt05SIDMPg3PTxZbdPw9dL&sign=DEqbE64SUB0qjRQGtu%2F0BPXN9YsSXM2zqLHT1X2ufDs%3D&scene=offlinePaymentNewSns"};
startActivity(webViewIntent);
}
public void openSettings(View view) {
Intent settingsIntent = new Intent(this, SettingsActivity.class);
settingsIntent.putExtra("title", getString(R.string.preference));
settingsIntent.putExtra("frag_id", "GeneralSettingsFragment");
startActivity(settingsIntent);
}
@Override
public void onAccessibilityStateChanged(boolean enabled) {
updateServiceStatus();
}
/**
* 更新当前 HongbaoService 显示状态
*/
private void updateServiceStatus() {
if (isServiceEnabled()) {
pluginStatusText.setText(R.string.service_off);
pluginStatusIcon.setBackgroundResource(R.mipmap.ic_stop);
} else {
pluginStatusText.setText(R.string.service_on);
pluginStatusIcon.setBackgroundResource(R.mipmap.ic_start);
}
}
/**
* 获取 HongbaoService 是否启用状态
*
* @return
*/
private boolean isServiceEnabled() {
List<AccessibilityServiceInfo> accessibilityServices =
accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
for (AccessibilityServiceInfo info : accessibilityServices) {
if (info.getId().equals(getPackageName() + "/.services.HongbaoService")) {
return true;
}
}
return false;
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/SeekBarPreference.java
================================================
package xyz.monkeytong.hongbao.activities;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;
import android.widget.TextView;
import xyz.monkeytong.hongbao.R;
/**
* Created by Zhongyi on 2/3/16.
*/
public class SeekBarPreference extends DialogPreference {
private SeekBar seekBar;
private TextView textView;
private String hintText, prefKind;
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setDialogLayoutResource(R.layout.preference_seekbar);
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attr = attrs.getAttributeName(i);
if (attr.equalsIgnoreCase("pref_kind")) {
prefKind = attrs.getAttributeValue(i);
break;
}
}
if (prefKind.equals("pref_open_delay")) {
hintText = getContext().getString(R.string.delay_open);
} else if (prefKind.equals("pref_comment_delay")) {
hintText = "发送回复(暂不支持延时)";
}
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
SharedPreferences pref = getSharedPreferences();
int delay = pref.getInt(prefKind, 0);
this.seekBar = (SeekBar) view.findViewById(R.id.delay_seekBar);
this.seekBar.setProgress(delay);
if (prefKind.equals("pref_comment_delay")) {
this.seekBar.setEnabled(false);
}
this.textView = (TextView) view.findViewById(R.id.pref_seekbar_textview);
setHintText(0);
this.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
setHintText(i);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
@Override
protected void onDialogClosed(boolean positiveResult) {
if (positiveResult) {
SharedPreferences.Editor editor = getEditor();
editor.putInt(prefKind, this.seekBar.getProgress());
editor.commit();
}
super.onDialogClosed(positiveResult);
}
private void setHintText(int delay) {
if (delay == 0) {
this.textView.setText(getContext().getString(R.string.delay_instantly) + hintText);
} else {
this.textView.setText(getContext().getString(R.string.delay_delay) + delay + getContext().getString(R.string.delay_sec) + getContext().getString(R.string.delay_then) + hintText);
}
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/SettingsActivity.java
================================================
package xyz.monkeytong.hongbao.activities;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import xyz.monkeytong.hongbao.R;
import xyz.monkeytong.hongbao.fragments.CommentSettingsFragment;
import xyz.monkeytong.hongbao.fragments.GeneralSettingsFragment;
import xyz.monkeytong.hongbao.utils.UpdateTask;
/**
* Created by Zhongyi on 1/19/16.
* Settings page.
*/
public class SettingsActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preferences);
loadUI();
prepareSettings();
}
private void prepareSettings() {
String title, fragId;
Bundle bundle = getIntent().getExtras();
if (bundle != null) {
title = bundle.getString("title");
fragId = bundle.getString("frag_id");
} else {
title = getString(R.string.preference);
fragId = "GeneralSettingsFragment";
}
TextView textView = (TextView) findViewById(R.id.settings_bar);
textView.setText(title);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if ("GeneralSettingsFragment".equals(fragId)) {
fragmentTransaction.replace(R.id.preferences_fragment, new GeneralSettingsFragment());
} else if ("CommentSettingsFragment".equals(fragId)) {
fragmentTransaction.replace(R.id.preferences_fragment, new CommentSettingsFragment());
}
fragmentTransaction.commit();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void loadUI() {
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
Window window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0xffE46C62);
}
@Override
protected void onResume() {
super.onResume();
}
public void performBack(View view) {
super.onBackPressed();
}
public void enterAccessibilityPage(View view) {
Toast.makeText(this, getString(R.string.turn_on_toast), Toast.LENGTH_SHORT).show();
Intent mAccessibleIntent =
new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivity(mAccessibleIntent);
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/WebViewActivity.java
================================================
package xyz.monkeytong.hongbao.activities;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.CookieSyncManager;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;
import xyz.monkeytong.hongbao.R;
import xyz.monkeytong.hongbao.utils.DownloadUtil;
/**
* Created by Zhongyi on 1/19/16.
* Settings page.
*/
public class WebViewActivity extends Activity {
private WebView webView;
private String webViewUrl, webViewTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadUI();
Bundle bundle = getIntent().getExtras();
if (bundle != null && !bundle.isEmpty()) {
webViewTitle = bundle.getString("title");
webViewUrl = bundle.getString("url");
final TextView webViewBar = (TextView) findViewById(R.id.webview_bar);
webViewBar.setText(webViewTitle);
webView = (WebView) findViewById(R.id.webView);
webView.getSettings().setBuiltInZoomControls(false);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("apk")) {
Toast.makeText(getApplicationContext(), getString(R.string.download_backend), Toast.LENGTH_SHORT).show();
(new DownloadUtil()).enqueue(url, getApplicationContext());
return true;
} else if (!url.contains("http")) {
Toast.makeText(getApplicationContext(), getString(R.string.download_redirect), Toast.LENGTH_LONG).show();
webViewBar.setText(getString(R.string.download_hint));
return false;
} else {
view.loadUrl(url);
return false;
}
}
@Override
public void onPageFinished(WebView view, String url) {
CookieSyncManager.getInstance().sync();
}
});
webView.loadUrl(webViewUrl);
}
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void loadUI() {
setContentView(R.layout.activity_webview);
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
Window window = this.getWindow();
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(0xffE46C62);
}
public void performBack(View view) {
super.onBackPressed();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
if (webView.canGoBack()) {
webView.goBack();
} else {
finish();
}
return true;
}
}
return super.onKeyDown(keyCode, event);
}
public void openLink(View view) {
Intent intent = new Intent(Intent.ACTION_VIEW,
Uri.parse(this.webViewUrl));
startActivity(intent);
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/fragments/CommentSettingsFragment.java
================================================
package xyz.monkeytong.hongbao.fragments;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.widget.Toast;
import xyz.monkeytong.hongbao.R;
/**
* Created by Zhongyi on 2/4/16.
*/
public class CommentSettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.comment_preferences);
setPrefListeners();
}
private void setPrefListeners() {
Preference updatePref = findPreference("pref_comment_switch");
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
updatePref.setEnabled(false);
}
Toast.makeText(getActivity(), "该功能尚处于实验中,只能自动填充感谢语,无法直接发送.", Toast.LENGTH_LONG).show();
Preference commentWordsPref = findPreference("pref_comment_words");
String summary = getResources().getString(R.string.pref_comment_words_summary);
String value = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("pref_comment_words", "");
if (value.length() > 0) commentWordsPref.setSummary(summary + ":" + value);
commentWordsPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
String summary = getResources().getString(R.string.pref_comment_words_summary);
if (o != null && o.toString().length() > 0) {
preference.setSummary(summary + ":" + o.toString());
} else {
preference.setSummary(summary);
}
return true;
}
});
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/fragments/GeneralSettingsFragment.java
================================================
package xyz.monkeytong.hongbao.fragments;
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import xyz.monkeytong.hongbao.R;
import xyz.monkeytong.hongbao.activities.WebViewActivity;
import xyz.monkeytong.hongbao.utils.UpdateTask;
/**
* Created by Zhongyi on 2/4/16.
*/
public class GeneralSettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.general_preferences);
setPrefListeners();
}
private void setPrefListeners() {
// Check for updates
Preference updatePref = findPreference("pref_etc_check_update");
updatePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
new UpdateTask(getActivity().getApplicationContext(), true).update();
return false;
}
});
// Open issue
Preference issuePref = findPreference("pref_etc_issue");
issuePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
Intent webViewIntent = new Intent(getActivity(), WebViewActivity.class);
webViewIntent.putExtra("title", "GitHub Issues");
webViewIntent.putExtra("url", getString(R.string.url_github_issues));
webViewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(webViewIntent);
return false;
}
});
Preference excludeWordsPref = findPreference("pref_watch_exclude_words");
String summary = getResources().getString(R.string.pref_watch_exclude_words_summary);
String value = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("pref_watch_exclude_words", "");
if (value.length() > 0) excludeWordsPref.setSummary(summary + ":" + value);
excludeWordsPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object o) {
String summary = getResources().getString(R.string.pref_watch_exclude_words_summary);
if (o != null && o.toString().length() > 0) {
preference.setSummary(summary + ":" + o.toString());
} else {
preference.setSummary(summary);
}
return true;
}
});
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/services/HongbaoService.java
================================================
package xyz.monkeytong.hongbao.services;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.GestureDescription;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcelable;
import android.graphics.Path;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.util.DisplayMetrics;
import xyz.monkeytong.hongbao.utils.HongbaoSignature;
import xyz.monkeytong.hongbao.utils.PowerUtil;
import java.util.List;
public class HongbaoService extends AccessibilityService implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "HongbaoService";
private static final String WECHAT_DETAILS_EN = "Details";
private static final String WECHAT_DETAILS_CH = "红包详情";
private static final String WECHAT_BETTER_LUCK_EN = "Better luck next time!";
private static final String WECHAT_BETTER_LUCK_CH = "手慢了";
private static final String WECHAT_EXPIRES_CH = "已超过24小时";
private static final String WECHAT_VIEW_SELF_CH = "查看红包";
private static final String WECHAT_VIEW_OTHERS_CH = "领取红包";
private static final String WECHAT_NOTIFICATION_TIP = "[微信红包]";
private static final String WECHAT_LUCKMONEY_RECEIVE_ACTIVITY = ".plugin.luckymoney.ui";//com.tencent.mm/.plugin.luckymoney.ui.En_fba4b94f com.tencent.mm/com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI
private static final String WECHAT_LUCKMONEY_DETAIL_ACTIVITY = "LuckyMoneyDetailUI";
private static final String WECHAT_LUCKMONEY_GENERAL_ACTIVITY = "LauncherUI";
private static final String WECHAT_LUCKMONEY_CHATTING_ACTIVITY = "ChattingUI";
private String currentActivityName = WECHAT_LUCKMONEY_GENERAL_ACTIVITY;
private AccessibilityNodeInfo rootNodeInfo, mReceiveNode, mUnpackNode;
private boolean mLuckyMoneyPicked, mLuckyMoneyReceived;
private int mUnpackCount = 0;
private boolean mMutex = false, mListMutex = false, mChatMutex = false;
private HongbaoSignature signature = new HongbaoSignature();
private PowerUtil powerUtil;
private SharedPreferences sharedPreferences;
/**
* AccessibilityEvent
*
* @param event 事件
*/
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (sharedPreferences == null) return;
setCurrentActivityName(event);
/* 检测通知消息 */
if (!mMutex) {
if (sharedPreferences.getBoolean("pref_watch_notification", false) && watchNotifications(event)) return;
if (sharedPreferences.getBoolean("pref_watch_list", false) && watchList(event)) return;
mListMutex = false;
}
if (!mChatMutex) {
mChatMutex = true;
if (sharedPreferences.getBoolean("pref_watch_chat", false)) watchChat(event);
mChatMutex = false;
}
}
private void watchChat(AccessibilityEvent event) {
this.rootNodeInfo = getRootInActiveWindow();
if (rootNodeInfo == null) return;
mReceiveNode = null;
mUnpackNode = null;
checkNodeInfo(event.getEventType());
/* 如果已经接收到红包并且还没有戳开 */
Log.d(TAG, "watchChat mLuckyMoneyReceived:" + mLuckyMoneyReceived + " mLuckyMoneyPicked:" + mLuckyMoneyPicked + " mReceiveNode:" + mReceiveNode);
if (mLuckyMoneyReceived && (mReceiveNode != null)) {
mMutex = true;
mReceiveNode.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
mLuckyMoneyReceived = false;
mLuckyMoneyPicked = true;
}
/* 如果戳开但还未领取 */
Log.d(TAG, "戳开红包!" + " mUnpackCount: " + mUnpackCount + " mUnpackNode: " + mUnpackNode);
if (mUnpackCount >= 1 && (mUnpackNode != null)) {
int delayFlag = sharedPreferences.getInt("pref_open_delay", 0) * 1000;
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
try {
openPacket();
} catch (Exception e) {
mMutex = false;
mLuckyMoneyPicked = false;
mUnpackCount = 0;
}
}
},
delayFlag);
}
}
private void openPacket() {
DisplayMetrics metrics = getResources().getDisplayMetrics();
float dpi = metrics.densityDpi;
Log.d(TAG, "openPacket!" + dpi);
if (android.os.Build.VERSION.SDK_INT <= 23) {
mUnpackNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);
} else {
if (android.os.Build.VERSION.SDK_INT > 23) {
Path path = new Path();
if (640 == dpi) { //1440
path.moveTo(720, 1575);
} else if(320 == dpi){//720p
path.moveTo(355, 780);
}else if(480 == dpi){//1080p
path.moveTo(533, 1115);
}
GestureDescription.Builder builder = new GestureDescription.Builder();
GestureDescription gestureDescription = builder.addStroke(new GestureDescription.StrokeDescription(path, 450, 50)).build();
dispatchGesture(gestureDescription, new GestureResultCallback() {
@Override
public void onCompleted(GestureDescription gestureDescription) {
Log.d(TAG, "onCompleted");
mMutex = false;
super.onCompleted(gestureDescription);
}
@Override
public void onCancelled(GestureDescription gestureDescription) {
Log.d(TAG, "onCancelled");
mMutex = false;
super.onCancelled(gestureDescription);
}
}, null);
}
}
}
private void setCurrentActivityName(AccessibilityEvent event) {
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
return;
}
try {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
getPackageManager().getActivityInfo(componentName, 0);
currentActivityName = componentName.flattenToShortString();
} catch (PackageManager.NameNotFoundException e) {
currentActivityName = WECHAT_LUCKMONEY_GENERAL_ACTIVITY;
}
}
private boolean watchList(AccessibilityEvent event) {
if (mListMutex) return false;
mListMutex = true;
AccessibilityNodeInfo eventSource = event.getSource();
// Not a message
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || eventSource == null)
return false;
List<AccessibilityNodeInfo> nodes = eventSource.findAccessibilityNodeInfosByText(WECHAT_NOTIFICATION_TIP);
//增加条件判断currentActivityName.contains(WECHAT_LUCKMONEY_GENERAL_ACTIVITY)
//避免当订阅号中出现标题为“[微信红包]拜年红包”(其实并非红包)的信息时误判
if (!nodes.isEmpty() && currentActivityName.contains(WECHAT_LUCKMONEY_GENERAL_ACTIVITY)) {
AccessibilityNodeInfo nodeToClick = nodes.get(0);
if (nodeToClick == null) return false;
CharSequence contentDescription = nodeToClick.getContentDescription();
if (contentDescription != null && !signature.getContentDescription().equals(contentDescription)) {
nodeToClick.performAction(AccessibilityNodeInfo.ACTION_CLICK);
signature.setContentDescription(contentDescription.toString());
return true;
}
}
return false;
}
private boolean watchNotifications(AccessibilityEvent event) {
// Not a notification
if (event.getEventType() != AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED)
return false;
// Not a hongbao
String tip = event.getText().toString();
if (!tip.contains(WECHAT_NOTIFICATION_TIP)) return true;
Parcelable parcelable = event.getParcelableData();
if (parcelable instanceof Notification) {
Notification notification = (Notification) parcelable;
try {
/* 清除signature,避免进入会话后误判 */
signature.cleanSignature();
notification.contentIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
return true;
}
@Override
public void onInterrupt() {
}
private AccessibilityNodeInfo findOpenButton(AccessibilityNodeInfo node) {
if (node == null)
return null;
//非layout元素
if (node.getChildCount() == 0) {
if ("android.widget.Button".equals(node.getClassName()))
return node;
else
return null;
}
//layout元素,遍历找button
AccessibilityNodeInfo button;
for (int i = 0; i < node.getChildCount(); i++) {
button = findOpenButton(node.getChild(i));
if (button != null)
return button;
}
return null;
}
private void checkNodeInfo(int eventType) {
if (this.rootNodeInfo == null) return;
if (signature.commentString != null) {
sendComment();
signature.commentString = null;
}
/* 聊天会话窗口,遍历节点匹配“领取红包”和"查看红包" */
AccessibilityNodeInfo node1 = (sharedPreferences.getBoolean("pref_watch_self", false)) ?
this.getTheLastNode(WECHAT_VIEW_OTHERS_CH, WECHAT_VIEW_SELF_CH) : this.getTheLastNode(WECHAT_VIEW_OTHERS_CH);
if (node1 != null &&
(currentActivityName.contains(WECHAT_LUCKMONEY_CHATTING_ACTIVITY)
|| currentActivityName.contains(WECHAT_LUCKMONEY_GENERAL_ACTIVITY))) {
String excludeWords = sharedPreferences.getString("pref_watch_exclude_words", "");
if (this.signature.generateSignature(node1, excludeWords)) {
mLuckyMoneyReceived = true;
mReceiveNode = node1;
Log.d("sig", this.signature.toString());
}
return;
}
/* 戳开红包,红包还没抢完,遍历节点匹配“拆红包” */
AccessibilityNodeInfo node2 = findOpenButton(this.rootNodeInfo);
Log.d(TAG, "checkNodeInfo node2 " + node2);
if (node2 != null && "android.widget.Button".equals(node2.getClassName()) && currentActivityName.contains(WECHAT_LUCKMONEY_RECEIVE_ACTIVITY)
&& (mUnpackNode == null || mUnpackNode != null && !mUnpackNode.equals(node2))) {
mUnpackNode = node2;
mUnpackCount += 1;
return;
}
/* 戳开红包,红包已被抢完,遍历节点匹配“红包详情”和“手慢了” */
boolean hasNodes = this.hasOneOfThoseNodes(
WECHAT_BETTER_LUCK_CH, WECHAT_DETAILS_CH,
WECHAT_BETTER_LUCK_EN, WECHAT_DETAILS_EN, WECHAT_EXPIRES_CH);
Log.d(TAG, "checkNodeInfo hasNodes:" + hasNodes + " mMutex:"+ mMutex);
if ( eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && hasNodes
&& (currentActivityName.contains(WECHAT_LUCKMONEY_DETAIL_ACTIVITY)
|| currentActivityName.contains(WECHAT_LUCKMONEY_RECEIVE_ACTIVITY))) {
mMutex = false;
mLuckyMoneyPicked = false;
mUnpackCount = 0;
performGlobalAction(GLOBAL_ACTION_BACK);
signature.commentString = generateCommentString();
}
}
private void sendComment() {
try {
AccessibilityNodeInfo outNode =
getRootInActiveWindow().getChild(0).getChild(0);
AccessibilityNodeInfo nodeToInput = outNode.getChild(outNode.getChildCount() - 1).getChild(0).getChild(1);
if ("android.widget.EditText".equals(nodeToInput.getClassName())) {
Bundle arguments = new Bundle();
arguments.putCharSequence(AccessibilityNodeInfo
.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, signature.commentString);
nodeToInput.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
}
} catch (Exception e) {
// Not supported
}
}
private boolean hasOneOfThoseNodes(String... texts) {
List<AccessibilityNodeInfo> nodes;
for (String text : texts) {
if (text == null) continue;
nodes = this.rootNodeInfo.findAccessibilityNodeInfosByText(text);
if (nodes != null && !nodes.isEmpty()) return true;
}
return false;
}
private AccessibilityNodeInfo getTheLastNode(String... texts) {
int bottom = 0;
AccessibilityNodeInfo lastNode = null, tempNode;
List<AccessibilityNodeInfo> nodes;
for (String text : texts) {
if (text == null) continue;
nodes = this.rootNodeInfo.findAccessibilityNodeInfosByText(text);
if (nodes != null && !nodes.isEmpty()) {
tempNode = nodes.get(nodes.size() - 1);
if (tempNode == null) return null;
Rect bounds = new Rect();
tempNode.getBoundsInScreen(bounds);
if (bounds.bottom > bottom) {
bottom = bounds.bottom;
lastNode = tempNode;
signature.others = text.equals(WECHAT_VIEW_OTHERS_CH);
}
}
}
return lastNode;
}
@Override
public void onServiceConnected() {
super.onServiceConnected();
this.watchFlagsFromPreference();
}
private void watchFlagsFromPreference() {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
this.powerUtil = new PowerUtil(this);
Boolean watchOnLockFlag = sharedPreferences.getBoolean("pref_watch_on_lock", false);
this.powerUtil.handleWakeLock(watchOnLockFlag);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals("pref_watch_on_lock")) {
Boolean changedValue = sharedPreferences.getBoolean(key, false);
this.powerUtil.handleWakeLock(changedValue);
}
}
@Override
public void onDestroy() {
this.powerUtil.handleWakeLock(false);
super.onDestroy();
}
private String generateCommentString() {
if (!signature.others) return null;
Boolean needComment = sharedPreferences.getBoolean("pref_comment_switch", false);
if (!needComment) return null;
String[] wordsArray = sharedPreferences.getString("pref_comment_words", "").split(" +");
if (wordsArray.length == 0) return null;
Boolean atSender = sharedPreferences.getBoolean("pref_comment_at", false);
if (atSender) {
return "@" + signature.sender + " " + wordsArray[(int) (Math.random() * wordsArray.length)];
} else {
return wordsArray[(int) (Math.random() * wordsArray.length)];
}
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/ConnectivityUtil.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* Created by Zhongyi on 1/29/16.
*/
public class ConnectivityUtil {
public static boolean isWifi(Context context) {
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting()
&& activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/DownloadUtil.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.app.DownloadManager;
import android.content.Context;
import android.net.Uri;
import android.os.Environment;
import java.net.URI;
import static android.content.Context.DOWNLOAD_SERVICE;
/**
* Created by Zhongyi on 8/1/16.
*/
public class DownloadUtil {
public void enqueue(String url, Context context) {
DownloadManager.Request r = new DownloadManager.Request(Uri.parse(url));
r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "Uber.apk");
r.allowScanningByMediaScanner();
r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
DownloadManager dm = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(r);
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoLogger.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by Zhongyi on 1/22/16.
*/
public class HongbaoLogger {
private Context context;
private SQLiteDatabase database;
private static final int DATABASE_VERSION = 1;
private static final String DATABASE_NAME = "WeChatLuckyMoney.db";
private static final String createDatabaseSQL = "CREATE TABLE IF NOT EXISTS HongbaoLog (id INTEGER PRIMARY KEY AUTOINCREMENT, sender TEXT, content TEXT, time TEXT, amount TEXT);";
public HongbaoLogger(final Context context) {
this.context = context;
this.initSchemaAndDatabase();
}
private void initSchemaAndDatabase() {
this.database = context.openOrCreateDatabase("WeChatLuckyMoney", context.MODE_PRIVATE, null);
this.database.beginTransaction();
this.database.execSQL(createDatabaseSQL);
this.database.endTransaction();
}
public void writeHongbaoLog(String sender, String content, String amount) {
}
public void getAllLogs() {
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoSignature.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.graphics.Rect;
import android.view.accessibility.AccessibilityNodeInfo;
/**
* Created by Zhongyi on 1/21/16.
*/
public class HongbaoSignature {
public String sender, content, time, contentDescription = "", commentString;
public boolean others;
public boolean generateSignature(AccessibilityNodeInfo node, String excludeWords) {
try {
/* The hongbao container node. It should be a LinearLayout. By specifying that, we can avoid text messages. */
AccessibilityNodeInfo hongbaoNode = node.getParent();
if (!"android.widget.LinearLayout".equals(hongbaoNode.getClassName())) return false;
/* The text in the hongbao. Should mean something. */
String hongbaoContent = hongbaoNode.getChild(0).getText().toString();
if (hongbaoContent == null || "查看红包".equals(hongbaoContent)) return false;
/* Check the user's exclude words list. */
String[] excludeWordsArray = excludeWords.split(" +");
for (String word : excludeWordsArray) {
if (word.length() > 0 && hongbaoContent.contains(word)) return false;
}
/* The container node for a piece of message. It should be inside the screen.
Or sometimes it will get opened twice while scrolling. */
AccessibilityNodeInfo messageNode = hongbaoNode.getParent();
Rect bounds = new Rect();
messageNode.getBoundsInScreen(bounds);
if (bounds.top < 0) return false;
/* The sender and possible timestamp. Should mean something too. */
String[] hongbaoInfo = getSenderContentDescriptionFromNode(messageNode);
if (this.getSignature(hongbaoInfo[0], hongbaoContent, hongbaoInfo[1]).equals(this.toString())) return false;
/* So far we make sure it's a valid new coming hongbao. */
this.sender = hongbaoInfo[0];
this.time = hongbaoInfo[1];
this.content = hongbaoContent;
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public String toString() {
return this.getSignature(this.sender, this.content, this.time);
}
private String getSignature(String... strings) {
String signature = "";
for (String str : strings) {
if (str == null) return null;
signature += str + "|";
}
return signature.substring(0, signature.length() - 1);
}
public String getContentDescription() {
return this.contentDescription;
}
public void setContentDescription(String description) {
this.contentDescription = description;
}
private String[] getSenderContentDescriptionFromNode(AccessibilityNodeInfo node) {
int count = node.getChildCount();
String[] result = {"unknownSender", "unknownTime"};
for (int i = 0; i < count; i++) {
AccessibilityNodeInfo thisNode = node.getChild(i);
if ("android.widget.ImageView".equals(thisNode.getClassName()) && "unknownSender".equals(result[0])) {
CharSequence contentDescription = thisNode.getContentDescription();
if (contentDescription != null) result[0] = contentDescription.toString().replaceAll("头像$", "");
} else if ("android.widget.TextView".equals(thisNode.getClassName()) && "unknownTime".equals(result[1])) {
CharSequence thisNodeText = thisNode.getText();
if (thisNodeText != null) result[1] = thisNodeText.toString();
}
}
return result;
}
public void cleanSignature() {
this.content = "";
this.time = "";
this.sender = "";
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/PowerUtil.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.PowerManager;
/**
* Created by Zhongyi on 1/29/16.
*/
public class PowerUtil {
private PowerManager.WakeLock wakeLock;
private KeyguardManager.KeyguardLock keyguardLock;
public PowerUtil(Context context) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
"HongbaoWakelock");
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
keyguardLock = km.newKeyguardLock("HongbaoKeyguardLock");
}
private void acquire() {
wakeLock.acquire(1800000);
keyguardLock.disableKeyguard();
}
private void release() {
if (wakeLock.isHeld()) {
wakeLock.release();
keyguardLock.reenableKeyguard();
}
}
public void handleWakeLock(boolean isWake) {
if (isWake) {
this.acquire();
} else {
this.release();
}
}
}
================================================
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/UpdateTask.java
================================================
package xyz.monkeytong.hongbao.utils;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.AsyncTask;
import android.widget.Toast;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import xyz.monkeytong.hongbao.R;
import xyz.monkeytong.hongbao.activities.SettingsActivity;
import xyz.monkeytong.hongbao.activities.WebViewActivity;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* Created by Zhongyi on 1/20/16.
* Util for app update task.
*/
public class UpdateTask extends AsyncTask<String, String, String> {
public static int count = 0;
private Context context;
private boolean isUpdateOnRelease;
public static final String updateUrl = "https://api.github.com/repos/geeeeeeeeek/WeChatLuckyMoney/releases/latest";
public UpdateTask(Context context, boolean needUpdate) {
this.context = context;
this.isUpdateOnRelease = needUpdate;
if (this.isUpdateOnRelease) Toast.makeText(context, context.getString(R.string.checking_new_version), Toast.LENGTH_SHORT).show();
}
@Override
protected String doInBackground(String... uri) {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try {
response = httpclient.execute(new HttpGet(uri[0]));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == 200) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
responseString = out.toString();
out.close();
} else {
// Close the connection.
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
} catch (Exception e) {
return null;
}
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
count += 1;
JSONObject release = new JSONObject(result);
// Get current version
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
String version = pInfo.versionName;
String latestVersion = release.getString("tag_name");
boolean isPreRelease = release.getBoolean("prerelease");
if (!isPreRelease && version.compareToIgnoreCase(latestVersion) >= 0) {
// Your version is ahead of or same as the latest.
if (this.isUpdateOnRelease)
Toast.makeText(context, R.string.update_already_latest, Toast.LENGTH_SHORT).show();
} else {
if (!isUpdateOnRelease) {
Toast.makeText(context, context.getString(R.string.update_new_seg1) + latestVersion + context.getString(R.string.update_new_seg3), Toast.LENGTH_LONG).show();
return;
}
// Need update.
String downloadUrl = release.getJSONArray("assets").getJSONObject(0).getString("browser_download_url");
// Give up on the fucking DownloadManager. The downloaded apk got renamed and unable to install. Fuck.
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(downloadUrl));
browserIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(browserIntent);
Toast.makeText(context, context.getString(R.string.update_new_seg1) + latestVersion + context.getString(R.string.update_new_seg2), Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
e.printStackTrace();
if (this.isUpdateOnRelease) Toast.makeText(context, R.string.update_error, Toast.LENGTH_LONG).show();
}
}
public void update() {
super.execute(updateUrl);
}
}
================================================
FILE: app/src/main/res/layout/activity_main.xml
================================================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff">
<ImageView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:id="@+id/main_action_bar_placeholder"
android:layout_alignParentTop="true"
android:background="#E46C62" android:contentDescription="@string/todo" />
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="@+id/layout_header"
android:layout_above="@+id/layout_control"
android:background="#E46C62"
android:layout_marginBottom="12dp">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView"
android:text="@string/app_name"
android:textColor="#fff"
android:gravity="center_vertical|center_horizontal"
android:textSize="28sp"
android:layout_marginTop="40dp"
android:textIsSelectable="false"/>
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/textView5"
android:text="@string/app_version"
android:textColor="#fff"
android:gravity="center_vertical|center_horizontal"
android:layout_marginTop="4dp"/>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@mipmap/bg_snow"
android:id="@+id/main_bg_snow"
android:layout_alignBottom="@id/layout_header" android:contentDescription="@string/todo" />
<LinearLayout android:id="@+id/layout_control"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="110dp"
android:layout_above="@+id/layout_alipay"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" android:baselineAligned="false">
<LinearLayout style="?android:attr/borderlessButtonStyle"
android:id="@+id/layout_control_community"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:textColor="#858585"
android:textSize="20sp"
android:orientation="vertical"
android:layout_weight="0.35"
android:layout_marginEnd="5dp"
android:onClick="openGitHub">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:id="@+id/imageView"
android:src="@mipmap/ic_community"
android:layout_margin="10dp" android:contentDescription="@string/todo" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/community"
android:id="@+id/textView2"
android:layout_margin="5dp"
android:textColor="#858585" android:textSize="16sp" android:textStyle="bold"/>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_control_accessibility"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:onClick="openAccessibility"
android:background="#ffffff"
android:textColor="#858585"
style="?android:attr/borderlessButtonStyle"
android:textSize="20sp"
android:orientation="vertical"
android:layout_weight="0.3"
android:layout_marginRight="5dp"
android:layout_marginLeft="5dp">
<ImageView android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/layout_control_accessibility_icon"
android:layout_marginBottom="6dp"
android:layout_marginTop="6dp"
android:background="@mipmap/ic_start" android:contentDescription="@string/todo" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/service_on"
android:id="@+id/layout_control_accessibility_text"
android:layout_margin="5dp"
android:textColor="#dfaa6a" android:textStyle="bold" android:textSize="16sp"/>
</LinearLayout>
<LinearLayout style="?android:attr/borderlessButtonStyle"
android:id="@+id/layout_control_settings"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:textColor="#858585"
android:textSize="20sp"
android:orientation="vertical"
android:layout_weight="0.35"
android:layout_marginStart="5dp"
android:onClick="openSettings">
<ImageView android:layout_width="24dp"
android:layout_height="24dp"
android:id="@+id/imageView4"
android:layout_margin="10dp"
android:src="@mipmap/ic_settings" android:contentDescription="@string/todo" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/settings"
android:id="@+id/textView3"
android:layout_margin="5dp"
android:textColor="#858585" android:textSize="16sp" android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/layout_alipay"
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_above="@+id/linearLayout2"
android:layout_alignParentBottom="false"
android:layout_marginBottom="8dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:background="#ffffff"
android:onClick="openUber"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon_uber"
android:layout_width="52dp"
android:layout_height="52dp"
android:layout_gravity="center_vertical"
android:layout_marginBottom="2dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/todo"
android:src="@mipmap/icon_alipay" />
<LinearLayout
android:id="@+id/layout_uber_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/label_uber_link"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="7dp"
android:text="@string/alipay_ad_text"
android:textColor="#e46c62"
android:textStyle="bold"
android:gravity="center" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/linearLayout2"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:background="#ffffff"
android:layout_marginTop="8dp"
android:layout_marginBottom="24dp"
android:onClick="openGitHub"
android:layout_alignParentBottom="true">
<ImageView android:layout_width="20dp"
android:layout_height="20dp"
android:id="@+id/imageView2"
android:src="@mipmap/ic_github"
android:layout_marginStart="15dp"
android:layout_marginEnd="5dp"
android:layout_gravity="center_vertical" android:contentDescription="@string/todo" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/github_1"
android:id="@+id/textView6"
android:layout_margin="2dp"
android:textColor="#858585"
android:layout_gravity="center_vertical"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/star_1"
android:id="@+id/textView7"
android:textColor="#dfaa6a"
android:layout_gravity="center_vertical"
android:paddingBottom="1dp"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView8"
android:text="@string/star_2"
android:textColor="#dfaa6a"
android:layout_gravity="center_vertical"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp" android:textStyle="bold"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/github_2"
android:id="@+id/textView9"
android:layout_margin="2dp"
android:textColor="#858585"
android:layout_gravity="center_vertical"/>
</LinearLayout>
</RelativeLayout>
================================================
FILE: app/src/main/res/layout/activity_preferences.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E46C62"
tools:context=".SettingsActivity"
>
<TextView android:layout_width="wrap_content" android:layout_height="54dp"
android:id="@+id/settings_bar"
android:text="@string/preference" android:textColor="#fff"
android:gravity="left|center_vertical|center_horizontal"
android:elegantTextHeight="false" android:textSize="18sp"
android:layout_toRightOf="@+id/preference_back"
/>
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:id="@+id/preference_back"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:clickable="true" android:onClick="performBack"
android:layout_alignBottom="@+id/settings_bar"
android:src="@mipmap/ic_back" android:padding="10dp"/>
<ImageView android:layout_width="40dp" android:layout_height="match_parent" android:id="@+id/imageView3"
android:clickable="true"
android:onClick="enterAccessibilityPage"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp" android:layout_marginStart="8dp"
android:padding="8dp" android:src="@mipmap/ic_refresh"
android:layout_alignBottom="@+id/settings_bar"/>
</RelativeLayout>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/preferences_fragment"
tools:layout="@android:layout/simple_list_item_1"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/activity_webview.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".activities.WebViewActivity">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E46C62"
tools:context=".WebViewActivity"
>
<TextView android:layout_width="wrap_content" android:layout_height="54dp"
android:id="@+id/webview_bar"
android:text="@string/app_name"
android:gravity="left|center_vertical|center_horizontal"
android:elegantTextHeight="false" android:textSize="18sp"
android:layout_toEndOf="@+id/webview_back"
android:textColor="#fff" tools:targetApi="lollipop"/>
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="@+id/webview_back"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:clickable="true" android:onClick="performBack"
android:layout_alignBottom="@+id/webview_bar"
android:src="@mipmap/ic_back" android:layout_alignParentBottom="false"
android:layout_alignParentTop="false" android:layout_alignParentStart="true"
android:cropToPadding="false" android:padding="10dp" android:focusable="true" android:contentDescription="@string/todo" />
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="@+id/webview_outlink"
android:layout_marginEnd="10dp"
android:clickable="true" android:onClick="openLink"
android:layout_alignBottom="@+id/webview_bar"
android:src="@mipmap/ic_open_in_browser" android:layout_alignParentEnd="true"
android:layout_marginStart="8dp" android:padding="8dp" android:contentDescription="@string/todo" android:focusable="true" />
</RelativeLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webView"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/preference_category.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingEnd="?android:attr/scrollbarSize" android:baselineAligned="false">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:layout_marginEnd="10dp"
android:layout_weight="1">
<TextView android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:textColor="#E46C62"
android:textSize="14sp"
android:fadingEdge="horizontal"/>
</RelativeLayout>
</LinearLayout>
================================================
FILE: app/src/main/res/layout/preference_checkbox.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="16dp"
android:paddingEnd="?android:attr/scrollbarSize" android:baselineAligned="false">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp"
android:layout_weight="1">
<TextView android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
android:textColor="#666666"
android:textSize="16sp"
android:fadingEdge="horizontal" />
<TextView android:id="@+android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textColor="#999"
android:textSize="14sp"
android:maxLines="4" />
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginEnd="6dp"
android:gravity="center"
android:orientation="vertical" />
</LinearLayout>
================================================
FILE: app/src/main/res/layout/preference_seekbar.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/delay_seekBar" android:layout_margin="20dp" android:max="10"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/d"
android:id="@+id/pref_seekbar_textview" android:textColor="#666666" android:textSize="16sp"
android:layout_marginLeft="32dp" android:layout_marginRight="32dp" android:layout_marginBottom="20dp"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout-v21/activity_preferences.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E46C62"
tools:context=".SettingsActivity"
>
<TextView android:layout_width="wrap_content" android:layout_height="54dp"
android:id="@+id/settings_bar"
android:text="@string/preference" android:textColor="#fff"
android:gravity="left|center_vertical|center_horizontal"
android:elegantTextHeight="false" android:textSize="18sp"
android:layout_toEndOf="@+id/preference_back"
/>
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:id="@+id/preference_back"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:clickable="true" android:onClick="performBack"
android:layout_alignBottom="@+id/settings_bar"
android:src="@mipmap/ic_back" android:padding="10dp" android:focusable="true" android:contentDescription="TODO" />
<ImageView android:layout_width="40dp" android:layout_height="match_parent" android:id="@+id/imageView3"
android:clickable="true"
android:onClick="enterAccessibilityPage"
android:layout_alignParentEnd="true"
android:layout_marginEnd="10dp" android:layout_marginStart="8dp"
android:padding="8dp" android:src="@mipmap/ic_refresh"
android:layout_alignBottom="@+id/settings_bar" android:focusable="true" android:contentDescription="@string/todo" />
</RelativeLayout>
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/preferences_fragment"
tools:layout="@android:layout/simple_list_item_1"/>
</LinearLayout>
================================================
FILE: app/src/main/res/layout-v21/activity_webview.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".activities.WebViewActivity">
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#E46C62"
tools:context=".WebViewActivity"
>
<TextView android:layout_width="wrap_content" android:layout_height="54dp"
android:id="@+id/webview_bar"
android:text="@string/app_name"
android:gravity="left|center_vertical|center_horizontal"
android:elegantTextHeight="false" android:textSize="18sp"
android:layout_toEndOf="@+id/webview_back"
android:textColor="#fff"/>
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="@+id/webview_back"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:clickable="true" android:onClick="performBack"
android:layout_alignBottom="@+id/webview_bar"
android:src="@mipmap/ic_back" android:layout_alignParentBottom="false"
android:layout_alignParentTop="false" android:layout_alignParentStart="true"
android:cropToPadding="false" android:padding="10dp" android:focusable="true" android:contentDescription="@string/todo" />
<ImageView
android:layout_width="40dp"
android:layout_height="fill_parent"
android:id="@+id/webview_outlink"
android:layout_marginEnd="10dp"
android:clickable="true" android:onClick="openLink"
android:layout_alignBottom="@+id/webview_bar"
android:src="@mipmap/ic_open_in_browser" android:layout_alignParentEnd="true"
android:layout_marginStart="8dp" android:padding="8dp" android:contentDescription="@string/todo" android:focusable="true" />
</RelativeLayout>
<WebView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/webView"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
<string name="app_name">微信红包</string>
<string name="app_version">v5.0</string>
<string name="app_description">∠( ᐛ 」∠)_使用指南∠( ᐛ 」∠)_\n\n ○ 狠戳插件开关\n ○ 回到微信聊天\n ○ 坐等红包进账\n\n 遇到问题, 欢迎通过 GitHub Issue 反馈~\n https://github.com/geeeeeeeeek/WeChatLuckyMoney</string>
<string name="preference">偏好设置</string>
<string name="update_error">遇到一些问题,请前往GitHub手动更新喵(ฅ´ω`ฅ)</string>
<string name="update_new_seg1">发现新版本(</string>
<string name="update_new_seg2">),正在为您准备下载( /) V (\\ )</string>
<string name="update_new_seg3">),请进入设置完成更新(ฅ´ω`ฅ)</string>
<string name="update_already_latest">已经是最新版本了(❁´▽`❁)</string>
<string name="service_off">关闭插件</string>
<string name="service_on">开启插件</string>
<string name="pref_watch_exclude_words_summary">不拆开包含这些文字的红包(空格间隔)</string>
<string name="pref_comment_words_summary">随机选择下列感谢语(空格间隔)</string>
<string name="url_github_issues">https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues</string>
<string name="home_banner_ad_unit_id">ca-app-pub-8428619221469478/4736153346</string>
<string name="webview_banner_ad_unit_id">ca-app-pub-8428619221469478/4163694548</string>
<string name="community">社区</string>
<string name="settings">设置</string>
<string name="alipay_ad_text">立即获得红包!人人可领!天天可领!</string>
<string name="github_1">在 GitHub 上</string>
<string name="github_2">本项目,支持应用开源</string>
<string name="star_2">Star</string>
<string name="star_1">★</string>
<string name="turn_on_toast">点击「微信红包」</string>
<string name="turn_on_error_toast">遇到一些问题,请手动打开系统设置>无障碍服务>微信红包(ฅ´ω`ฅ)</string>
<string name="webview_github_title">GitHub 项目主页</string>
<string name="webview_alipay_title">支付宝红包</string>
<string name="download_backend">正在后台下载</string>
<string name="download_redirect">正在前往下载页面</string>
<string name="download_hint">点击\"普通下载\"获取 Uber</string>
<string name="watch_options">监视选项</string>
<string name="watch_notifications">监视系统通知</string>
<string name="watch_notifications_hint">读取新消息通知中的红包提示并进入聊天页</string>
<string name="watch_list">监视聊天列表</string>
<string name="watch_list_hint">读取聊天列表中的红包提示并进入聊天页</string>
<string name="anti_block_options">防封号选项</string>
<string name="auto_open_packets">自动拆开红包</string>
<string name="open_with_delay">延时拆开红包</string>
<string name="open_self">拆开自己发的红包</string>
<string name="skip_phrases">屏蔽红包文字</string>
<string name="about">关于应用</string>
<string name="check_new_version">检查新版本</string>
<string name="help_and_feedback">帮助与反馈</string>
<string name="help_hint">前往GitHub项目主页提交issue</string>
<string name="labs">实验功能</string>
<string name="snatch_on_lockscreen">息屏抢红包</string>
<string name="snatch_on_lockscreen_hint">保持30分钟后台活跃,可能会极大增加电量消耗,请谨慎使用</string>
<string name="auto_reply">拆开红包后自动回复</string>
<string name="checking_new_version">正在检查新版本……</string>
<string name="delay_instantly">立即</string>
<string name="delay_delay">延迟</string>
<string name="delay_open">拆开红包</string>
<string name="delay_sec">秒</string>
<string name="delay_then">然后</string>
<string name="d">延迟0秒拆开红包</string>
<string name="todo">TODO</string>
</resources>
================================================
FILE: app/src/main/res/values-en/strings.xml
================================================
<resources>
<string name="app_name">Lucky Money</string>
<string name="app_version">v5.0</string>
<string name="app_description">∠( ᐛ 」∠)_ Instructions ∠( ᐛ 」∠)_\n\n ○ Turn on the Accessibility switch\n ○ Go back to WeChat\n ○ Wait for money comes in\n\n Please submit your feedback on GitHub Issues Page~\n https://github.com/geeeeeeeeek/WeChatLuckyMoney</string>
<string name="preference">Preferences</string>
<string name="update_error">An error occurred. Please manually update from GitHub Release Page. (ฅ´ω`ฅ)</string>
<string name="update_new_seg1">New version found.(</string>
<string name="update_new_seg2">)Preparing download for you. ( /) V (\\ )</string>
<string name="update_new_seg3">)Please go to Settings to finish update. (ฅ´ω`ฅ)</string>
<string name="update_already_latest">You\'re using the latest version! (❁´▽`❁)</string>
<string name="service_off">Turn Off</string>
<string name="service_on">Turn On</string>
<string name="pref_watch_exclude_words_summary">Skip red packets with these phrases (separated by space)</string>
<string name="pref_comment_words_summary">Randomly choose reply from these phrases (separated by space)</string>
<string name="url_github_issues">https://github.com/geeeeeeeeek/WeChatLuckyMoney/issues</string>
<string name="home_banner_ad_unit_id">ca-app-pub-8428619221469478/4736153346</string>
<string name="webview_banner_ad_unit_id">ca-app-pub-8428619221469478/4163694548</string>
<string name="community">Community</string>
<string name="settings">Settings</string>
<string name="alipay_ad_text">Get Luckymoney Now</string>
<string name="github_1"/>
<string name="github_2">this app on GitHub to support us</string>
<string name="star_2">Star</string>
<string name="star_1">★</string>
<string name="turn_on_toast">Click 「WeChat Lucky Money」 </string>
<string name="turn_on_error_toast">An error occurred. Please manually open System Settings > Accessibility > WeChat Lucky Money. (ฅ´ω`ฅ)</string>
<string name="webview_github_title">Project Homepage on GitHub</string>
<string name="webview_alipay_title">Get Luckymoney</string>
<string name="download_backend">Downloading…</string>
<string name="download_redirect">Redirecting to download page…</string>
<string name="download_hint">Download Uber by clicking \"普通下载\"</string>
<string name="watch_options">Watch Level</string>
<string name="watch_notifications">Watch system notifications</string>
<string name="watch_notifications_hint">Enter chat when a red packet is detected from WeChat notifications</string>
<string name="watch_list">Watch chat list</string>
<string name="watch_list_hint">Enter chat when a red packet is detected from chat list</string>
<string name="anti_block_options">Anti-block Options</string>
<string name="auto_open_packets">Open red packets automatically</string>
<string name="open_with_delay">Open red packets with a delay</string>
<string name="open_self">Open red packets I gave out</string>
<string name="skip_phrases">Skip red packets by words in the message</string>
<string name="about">About</string>
<string name="check_new_version">Check for updates</string>
<string name="help_and_feedback">Help and feedback</string>
<string name="help_hint">Submit issues on GitHub homepage</string>
<string name="labs">Labs</string>
<string name="snatch_on_lockscreen">Snatch red packets on lock screen</string>
<string name="snatch_on_lockscreen_hint">Will keep the app active in backend for 30 min. Please proceed with caution, since this might greatly increase your battery usage.</string>
<string name="auto_reply">Auto reply</string>
<string name="checking_new_version">Checking for updates…</string>
<string name="delay_instantly">Instantly </string>
<string name="delay_delay">Delay for </string>
<string name="delay_open">open red packets.</string>
<string name="delay_sec"> seconds </string>
<string name="delay_then">and then </string>
<string name="d">延迟0秒拆开红包</string>
<string name="todo">TODO</string>
</resources>
================================================
FILE: app/src/main/res/values-w820dp/dimens.xml
================================================
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
================================================
FILE: app/src/main/res/values-w820dp/strings.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="d">延迟0秒拆开红包</string>
<string name="todo">TODO</string>
</resources>
================================================
FILE: app/src/main/res/xml/accessible_service_config.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_description"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeNotificationStateChanged"
android:accessibilityFeedbackType="feedbackAllMask"
android:packageNames="com.tencent.mm"
android:notificationTimeout="10"
android:settingsActivity="xyz.monkeytong.hongbao.activities.SettingsActivity"
android:accessibilityFlags="flagDefault"
android:canRetrieveWindowContent="true"/>
================================================
FILE: app/src/main/res/xml/comment_preferences.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:context=".SettingsActivity"
android:icon="@null">
<PreferenceCategory
android:title="自动回复(Android 5.0以上系统)"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="pref_comment_switch"
android:title="开启自动回复"
android:summary="在拆开其他人的红包后发送自动回复"
android:defaultValue="false"
android:layout="@layout/preference_checkbox"/>
</PreferenceCategory>
<PreferenceCategory
android:title="回复选项"
android:layout="@layout/preference_category">
<xyz.monkeytong.hongbao.activities.SeekBarPreference
android:key="pref_comment_delay"
android:title="延时发送回复"
pref_kind="pref_comment_delay"
android:layout="@layout/preference_checkbox"/>
<CheckBoxPreference
android:key="pref_comment_at"
android:title="\@发红包的人"
android:layout="@layout/preference_checkbox"
android:defaultValue="false"/>
<EditTextPreference
android:key="pref_comment_words"
android:title="自定义回复内容"
android:summary="@string/pref_comment_words_summary"
android:layout="@layout/preference_checkbox"/>
</PreferenceCategory>
</PreferenceScreen>
================================================
FILE: app/src/main/res/xml/general_preferences.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:context=".SettingsActivity"
android:icon="@null">
<PreferenceCategory
android:title="@string/watch_options"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="pref_watch_notification"
android:title="@string/watch_notifications"
android:summary="@string/watch_notifications_hint"
android:defaultValue="true"
android:layout="@layout/preference_checkbox"/>
<CheckBoxPreference
android:key="pref_watch_list"
android:title="@string/watch_list"
android:summary="@string/watch_list_hint"
android:layout="@layout/preference_checkbox"
android:defaultValue="false"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/anti_block_options"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="pref_watch_chat"
android:title="@string/auto_open_packets"
android:layout="@layout/preference_checkbox"
android:defaultValue="true"/>
<xyz.monkeytong.hongbao.activities.SeekBarPreference
android:key="pref_open_delay"
android:title="@string/open_with_delay"
pref_kind="pref_open_delay"
android:layout="@layout/preference_checkbox"/>
<CheckBoxPreference
android:key="pref_watch_self"
android:title="@string/open_self"
android:layout="@layout/preference_checkbox"
android:defaultValue="true"/>
<EditTextPreference
android:key="pref_watch_exclude_words"
android:title="@string/skip_phrases"
android:summary="@string/pref_watch_exclude_words_summary"
android:layout="@layout/preference_checkbox"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/about"
android:layout="@layout/preference_category">
<Preference
android:key="pref_etc_check_update"
android:title="@string/check_new_version"
android:summary="http://dwz.cn/WeChatLuckyMoney"
android:layout="@layout/preference_checkbox"/>
<Preference
android:key="pref_etc_issue"
android:title="@string/help_and_feedback"
android:summary="@string/help_hint"
android:layout="@layout/preference_checkbox"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/labs"
android:layout="@layout/preference_category">
<CheckBoxPreference
android:key="pref_watch_on_lock"
android:title="@string/snatch_on_lockscreen"
android:summary="@string/snatch_on_lockscreen_hint"
android:layout="@layout/preference_checkbox"
android:defaultValue="false"/>
</PreferenceCategory>
</PreferenceScreen>
================================================
FILE: app/src/main/res/xml/provider_paths.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
<external-path name="beta_external_path" path="Download/"/>
<!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
<external-path name="beta_external_files_path" path="Android/data/"/>
</paths>
================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
maven {
url 'https://maven.google.com/'
name 'Google'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
google()
}
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Sat Jan 27 19:41:50 CST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
================================================
FILE: gradle.properties
================================================
## Project-wide Gradle settings.
#
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Sat Jan 27 19:37:03 CST 2018
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=1087
android.useDeprecatedNdk=true
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle
================================================
include ':app'
gitextract_2tar33oo/ ├── .gitignore ├── .idea/ │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── inspectionProfiles/ │ │ └── Project_Default.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ ├── uiDesigner.xml │ └── vcs.xml ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── README_EN.md ├── WeChatLuckyMoney.iml ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ ├── java/ │ │ └── xyz/ │ │ └── monkeytong/ │ │ └── hongbao/ │ │ ├── activities/ │ │ │ ├── MainActivity.java │ │ │ ├── SeekBarPreference.java │ │ │ ├── SettingsActivity.java │ │ │ └── WebViewActivity.java │ │ ├── fragments/ │ │ │ ├── CommentSettingsFragment.java │ │ │ └── GeneralSettingsFragment.java │ │ ├── services/ │ │ │ └── HongbaoService.java │ │ └── utils/ │ │ ├── ConnectivityUtil.java │ │ ├── DownloadUtil.java │ │ ├── HongbaoLogger.java │ │ ├── HongbaoSignature.java │ │ ├── PowerUtil.java │ │ └── UpdateTask.java │ └── res/ │ ├── layout/ │ │ ├── activity_main.xml │ │ ├── activity_preferences.xml │ │ ├── activity_webview.xml │ │ ├── preference_category.xml │ │ ├── preference_checkbox.xml │ │ └── preference_seekbar.xml │ ├── layout-v21/ │ │ ├── activity_preferences.xml │ │ └── activity_webview.xml │ ├── values/ │ │ ├── dimens.xml │ │ └── strings.xml │ ├── values-en/ │ │ └── strings.xml │ ├── values-w820dp/ │ │ ├── dimens.xml │ │ └── strings.xml │ └── xml/ │ ├── accessible_service_config.xml │ ├── comment_preferences.xml │ ├── general_preferences.xml │ └── provider_paths.xml ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── monkeytong.jks.enc └── settings.gradle
SYMBOL INDEX (86 symbols across 13 files)
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/MainActivity.java
class MainActivity (line 27) | public class MainActivity extends Activity implements AccessibilityManag...
method onCreate (line 35) | @Override
method explicitlyLoadPreferences (line 54) | private void explicitlyLoadPreferences() {
method handleMaterialStatusBar (line 61) | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
method onPause (line 76) | @Override
method onResume (line 81) | @Override
method onDestroy (line 91) | @Override
method openAccessibility (line 98) | public void openAccessibility(View view) {
method openGitHub (line 110) | public void openGitHub(View view) {
method openUber (line 117) | public void openUber(View view) {
method openSettings (line 124) | public void openSettings(View view) {
method onAccessibilityStateChanged (line 132) | @Override
method updateServiceStatus (line 140) | private void updateServiceStatus() {
method isServiceEnabled (line 155) | private boolean isServiceEnabled() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/SeekBarPreference.java
class SeekBarPreference (line 15) | public class SeekBarPreference extends DialogPreference {
method SeekBarPreference (line 20) | public SeekBarPreference(Context context, AttributeSet attrs) {
method onBindDialogView (line 38) | @Override
method onDialogClosed (line 73) | @Override
method setHintText (line 83) | private void setHintText(int delay) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/SettingsActivity.java
class SettingsActivity (line 33) | public class SettingsActivity extends FragmentActivity {
method onCreate (line 34) | @Override
method prepareSettings (line 43) | private void prepareSettings() {
method loadUI (line 68) | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
method onResume (line 81) | @Override
method performBack (line 86) | public void performBack(View view) {
method enterAccessibilityPage (line 90) | public void enterAccessibilityPage(View view) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/activities/WebViewActivity.java
class WebViewActivity (line 26) | public class WebViewActivity extends Activity {
method onCreate (line 30) | @Override
method onPause (line 75) | @Override
method onResume (line 80) | @Override
method onDestroy (line 85) | @Override
method loadUI (line 90) | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
method performBack (line 105) | public void performBack(View view) {
method onKeyDown (line 109) | @Override
method openLink (line 126) | public void openLink(View view) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/fragments/CommentSettingsFragment.java
class CommentSettingsFragment (line 14) | public class CommentSettingsFragment extends PreferenceFragment {
method onCreate (line 15) | @Override
method setPrefListeners (line 22) | private void setPrefListeners() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/fragments/GeneralSettingsFragment.java
class GeneralSettingsFragment (line 15) | public class GeneralSettingsFragment extends PreferenceFragment {
method onCreate (line 16) | @Override
method setPrefListeners (line 23) | private void setPrefListeners() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/services/HongbaoService.java
class HongbaoService (line 24) | public class HongbaoService extends AccessibilityService implements Shar...
method onAccessibilityEvent (line 54) | @Override
method watchChat (line 74) | private void watchChat(AccessibilityEvent event) {
method openPacket (line 113) | private void openPacket() {
method setCurrentActivityName (line 151) | private void setCurrentActivityName(AccessibilityEvent event) {
method watchList (line 169) | private boolean watchList(AccessibilityEvent event) {
method watchNotifications (line 193) | private boolean watchNotifications(AccessibilityEvent event) {
method onInterrupt (line 217) | @Override
method findOpenButton (line 222) | private AccessibilityNodeInfo findOpenButton(AccessibilityNodeInfo nod...
method checkNodeInfo (line 244) | private void checkNodeInfo(int eventType) {
method sendComment (line 293) | private void sendComment() {
method hasOneOfThoseNodes (line 311) | private boolean hasOneOfThoseNodes(String... texts) {
method getTheLastNode (line 323) | private AccessibilityNodeInfo getTheLastNode(String... texts) {
method onServiceConnected (line 348) | @Override
method watchFlagsFromPreference (line 354) | private void watchFlagsFromPreference() {
method onSharedPreferenceChanged (line 363) | @Override
method onDestroy (line 371) | @Override
method generateCommentString (line 377) | private String generateCommentString() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/ConnectivityUtil.java
class ConnectivityUtil (line 10) | public class ConnectivityUtil {
method isWifi (line 11) | public static boolean isWifi(Context context) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/DownloadUtil.java
class DownloadUtil (line 15) | public class DownloadUtil {
method enqueue (line 16) | public void enqueue(String url, Context context) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoLogger.java
class HongbaoLogger (line 10) | public class HongbaoLogger {
method HongbaoLogger (line 18) | public HongbaoLogger(final Context context) {
method initSchemaAndDatabase (line 23) | private void initSchemaAndDatabase() {
method writeHongbaoLog (line 31) | public void writeHongbaoLog(String sender, String content, String amou...
method getAllLogs (line 35) | public void getAllLogs() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoSignature.java
class HongbaoSignature (line 9) | public class HongbaoSignature {
method generateSignature (line 13) | public boolean generateSignature(AccessibilityNodeInfo node, String ex...
method toString (line 52) | @Override
method getSignature (line 57) | private String getSignature(String... strings) {
method getContentDescription (line 67) | public String getContentDescription() {
method setContentDescription (line 71) | public void setContentDescription(String description) {
method getSenderContentDescriptionFromNode (line 75) | private String[] getSenderContentDescriptionFromNode(AccessibilityNode...
method cleanSignature (line 91) | public void cleanSignature() {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/PowerUtil.java
class PowerUtil (line 10) | public class PowerUtil {
method PowerUtil (line 14) | public PowerUtil(Context context) {
method acquire (line 22) | private void acquire() {
method release (line 27) | private void release() {
method handleWakeLock (line 34) | public void handleWakeLock(boolean isWake) {
FILE: app/src/main/java/xyz/monkeytong/hongbao/utils/UpdateTask.java
class UpdateTask (line 26) | public class UpdateTask extends AsyncTask<String, String, String> {
method UpdateTask (line 32) | public UpdateTask(Context context, boolean needUpdate) {
method doInBackground (line 38) | @Override
method onPostExecute (line 62) | @Override
method update (line 99) | public void update() {
Condensed preview — 59 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (137K chars).
[
{
"path": ".gitignore",
"chars": 146,
"preview": "*.imi\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n/.idea/dictionaries\n/mo"
},
{
"path": ".idea/compiler.xml",
"chars": 686,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"CompilerConfiguration\">\n <resourceExt"
},
{
"path": ".idea/copyright/profiles_settings.xml",
"chars": 74,
"preview": "<component name=\"CopyrightManager\">\n <settings default=\"\" />\n</component>"
},
{
"path": ".idea/encodings.xml",
"chars": 159,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"Encoding\">\n <file url=\"PROJECT\" chars"
},
{
"path": ".idea/gradle.xml",
"chars": 753,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"GradleSettings\">\n <option name=\"linke"
},
{
"path": ".idea/inspectionProfiles/Project_Default.xml",
"chars": 269,
"preview": "<component name=\"InspectionProjectProfileManager\">\n <profile version=\"1.0\">\n <option name=\"myName\" value=\"Project De"
},
{
"path": ".idea/misc.xml",
"chars": 1753,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"FrameworkDetectionExcludesConfiguration\""
},
{
"path": ".idea/modules.xml",
"chars": 369,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectModuleManager\">\n <modules>\n "
},
{
"path": ".idea/runConfigurations.xml",
"chars": 564,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"RunConfigurationProducerService\">\n <o"
},
{
"path": ".idea/uiDesigner.xml",
"chars": 8792,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"Palette2\">\n <group name=\"Swing\">\n "
},
{
"path": ".idea/vcs.xml",
"chars": 180,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"VcsDirectoryMappings\">\n <mapping dire"
},
{
"path": ".travis.yml",
"chars": 1778,
"preview": "language: android\nsudo: false\njdk: oraclejdk8\nenv:\n matrix:\n - ANDROID_TARGET=android-26 ANDROID_ABI=armeabi-v7a arme"
},
{
"path": "CHANGELOG.md",
"chars": 3437,
"preview": "# 更新日志\n\n**[v4.0 (2017.01.27)](https://github.com/geeeeeeeeek/WeChatLuckyMoney/releases/tag/v4.0)**\n\n- 新年快乐!\n- 新增 多语言支持,目"
},
{
"path": "LICENSE.md",
"chars": 1139,
"preview": "**The MIT License (MIT)**\n\nCopyright (c) 2016 Zhongyi Tong ([geeeeeeeeek@Github](https://github.com/geeeeeeeeek))\n\nPermi"
},
{
"path": "README.md",
"chars": 2005,
"preview": "# 微信红包\n\n[](https://gitter.im/geeeeeeeeek/WeChatLucky"
},
{
"path": "README_EN.md",
"chars": 2811,
"preview": "# WeChat Lucky Money\n\n[](https://gitter.im/geeeeeeee"
},
{
"path": "WeChatLuckyMoney.iml",
"chars": 893,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module external.linked.project.id=\"WeChatLuckyMoney\" external.linked.project.pat"
},
{
"path": "app/.gitignore",
"chars": 451,
"preview": "# Built application files\n*.apk\n*.ap_\n\n# Files for the ART/Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated file"
},
{
"path": "app/build.gradle",
"chars": 1544,
"preview": " apply plugin: 'com.android.application'\n\nandroid {\n compileSdkVersion 25\n buildToolsVersion \"26.0.2\"\n useLibra"
},
{
"path": "app/proguard-rules.pro",
"chars": 762,
"preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /h"
},
{
"path": "app/src/main/AndroidManifest.xml",
"chars": 2792,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n pa"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/activities/MainActivity.java",
"chars": 5855,
"preview": "package xyz.monkeytong.hongbao.activities;\n\nimport android.accessibilityservice.AccessibilityServiceInfo;\nimport android"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/activities/SeekBarPreference.java",
"chars": 2887,
"preview": "package xyz.monkeytong.hongbao.activities;\n\nimport android.content.Context;\nimport android.content.SharedPreferences;\nim"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/activities/SettingsActivity.java",
"chars": 3167,
"preview": "package xyz.monkeytong.hongbao.activities;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport and"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/activities/WebViewActivity.java",
"chars": 4231,
"preview": "package xyz.monkeytong.hongbao.activities;\n\nimport android.annotation.TargetApi;\nimport android.app.Activity;\nimport and"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/fragments/CommentSettingsFragment.java",
"chars": 1903,
"preview": "package xyz.monkeytong.hongbao.fragments;\n\nimport android.os.Build;\nimport android.os.Bundle;\nimport android.preference."
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/fragments/GeneralSettingsFragment.java",
"chars": 2783,
"preview": "package xyz.monkeytong.hongbao.fragments;\n\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.prefe"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/services/HongbaoService.java",
"chars": 15773,
"preview": "package xyz.monkeytong.hongbao.services;\n\nimport android.accessibilityservice.AccessibilityService;\nimport android.acces"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/ConnectivityUtil.java",
"chars": 626,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport an"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/DownloadUtil.java",
"chars": 798,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.app.DownloadManager;\nimport android.content.Context;\nimport androi"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoLogger.java",
"chars": 1153,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.content.Context;\nimport android.database.sqlite.SQLiteDatabase;\nim"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/HongbaoSignature.java",
"chars": 3852,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.graphics.Rect;\nimport android.view.accessibility.AccessibilityNode"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/PowerUtil.java",
"chars": 1180,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.app.KeyguardManager;\nimport android.content.Context;\nimport androi"
},
{
"path": "app/src/main/java/xyz/monkeytong/hongbao/utils/UpdateTask.java",
"chars": 4276,
"preview": "package xyz.monkeytong.hongbao.utils;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.con"
},
{
"path": "app/src/main/res/layout/activity_main.xml",
"chars": 10900,
"preview": "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"http://schemas.and"
},
{
"path": "app/src/main/res/layout/activity_preferences.xml",
"chars": 2213,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/activity_webview.xml",
"chars": 2584,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/preference_category.xml",
"chars": 1007,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/preference_checkbox.xml",
"chars": 1908,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout/preference_seekbar.xml",
"chars": 845,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout-v21/activity_preferences.xml",
"chars": 2335,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/layout-v21/activity_webview.xml",
"chars": 2557,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n "
},
{
"path": "app/src/main/res/values/dimens.xml",
"chars": 211,
"preview": "<resources>\n <!-- Default screen margins, per the Android Design guidelines. -->\n <dimen name=\"activity_horizontal"
},
{
"path": "app/src/main/res/values/strings.xml",
"chars": 3226,
"preview": "<resources>\n <string name=\"app_name\">微信红包</string>\n <string name=\"app_version\">v5.0</string>\n <string name=\"app"
},
{
"path": "app/src/main/res/values-en/strings.xml",
"chars": 4213,
"preview": "<resources>\n <string name=\"app_name\">Lucky Money</string>\n <string name=\"app_version\">v5.0</string>\n <string na"
},
{
"path": "app/src/main/res/values-w820dp/dimens.xml",
"chars": 358,
"preview": "<resources>\n <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n (such as s"
},
{
"path": "app/src/main/res/values-w820dp/strings.xml",
"chars": 140,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n <string name=\"d\">延迟0秒拆开红包</string>\n <string name=\"todo\">TODO</"
},
{
"path": "app/src/main/res/xml/accessible_service_config.xml",
"chars": 597,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<accessibility-service\n xmlns:android=\"http://schemas.android.com/apk/res/andr"
},
{
"path": "app/src/main/res/xml/comment_preferences.xml",
"chars": 1597,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen xmlns:tools=\"http://schemas.android.com/tools\"\n "
},
{
"path": "app/src/main/res/xml/general_preferences.xml",
"chars": 3343,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen xmlns:tools=\"http://schemas.android.com/tools\"\n "
},
{
"path": "app/src/main/res/xml/provider_paths.xml",
"chars": 392,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<paths xmlns:android=\"http://schemas.android.com/apk/res/android\">\n <!-- /stor"
},
{
"path": "build.gradle",
"chars": 548,
"preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n r"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 230,
"preview": "#Sat Jan 27 19:41:50 CST 2018\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradle.properties",
"chars": 850,
"preview": "## Project-wide Gradle settings.\n#\n# For more details on how to configure your build environment visit\n# http://www.grad"
},
{
"path": "gradlew",
"chars": 5080,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2404,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
},
{
"path": "settings.gradle",
"chars": 15,
"preview": "include ':app'\n"
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the zhongyi-tong/WeChatLuckyMoney GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 59 files (124.4 KB), approximately 32.0k tokens, and a symbol index with 86 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.