├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── dictionaries │ └── .xml ├── gradle.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── alipayc.jpg ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lhy │ │ └── xposed │ │ └── mhzs │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ ├── help.html │ │ └── xposed_init │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── lhy │ │ │ └── xposed │ │ │ └── mhzs │ │ │ ├── HookLoader.java │ │ │ ├── HookMain.java │ │ │ ├── MHApplicaiton.java │ │ │ ├── activity │ │ │ ├── AboutActivity.java │ │ │ ├── AdSettingActivity.java │ │ │ ├── AppCompatPreferenceActivity.java │ │ │ ├── BaseActivity.java │ │ │ ├── ExpSettingActivity.java │ │ │ ├── FeedbackActivity.java │ │ │ ├── HelpActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── SettingsActivity.java │ │ │ └── TabSettingActivity.java │ │ │ ├── bean │ │ │ ├── DataBean.java │ │ │ ├── Feedback.java │ │ │ ├── M3u8FormatBean.java │ │ │ └── VideoInfoBean.java │ │ │ ├── fragment │ │ │ ├── AdSettingFragment.java │ │ │ ├── BasePreferenceFragment.java │ │ │ ├── ExpSettingFragment.java │ │ │ ├── SettingFragment.java │ │ │ └── TabSettingFragment.java │ │ │ ├── helper │ │ │ ├── Config.java │ │ │ ├── Constant.java │ │ │ ├── FileUtils.java │ │ │ ├── HYHelper.java │ │ │ ├── LogUtil.java │ │ │ ├── ToastUtils.java │ │ │ └── XPrefUtils.java │ │ │ ├── permission │ │ │ ├── PermissionHelper.java │ │ │ ├── PermissionInterface.java │ │ │ └── PermissionUtil.java │ │ │ └── plugin │ │ │ ├── AutoSignPlugin.java │ │ │ ├── ClearBootAdPlugin.java │ │ │ ├── ClearDanmuPlugin.java │ │ │ ├── ClearFiveSecondsPlugin.java │ │ │ ├── ClearMainAdPlugin.java │ │ │ ├── ClearMarqueePlugin.java │ │ │ ├── ClearMyFragmentAdPlugin.java │ │ │ ├── ClearPlayerAdPlugin.java │ │ │ ├── CustomMainInterfacePlugin.java │ │ │ ├── DownloadPlugin.java │ │ │ ├── HideDanmuPlugin.java │ │ │ ├── IPlugin.java │ │ │ ├── InfiniteCachePlugin.java │ │ │ ├── NoUpdatePlugin.java │ │ │ ├── SharePlugin.java │ │ │ ├── TVPlugin.java │ │ │ ├── TemplatePlugin.java │ │ │ ├── VideoURLPlugin.java │ │ │ ├── WatchThirtyMinutesPlugin.java │ │ │ └── WechatSharePlugin.java │ └── res │ │ ├── drawable-hdpi │ │ ├── bmob_update_btn_check_off_focused_holo_light.png │ │ ├── bmob_update_btn_check_off_holo_light.png │ │ ├── bmob_update_btn_check_off_pressed_holo_light.png │ │ ├── bmob_update_btn_check_on_focused_holo_light.png │ │ ├── bmob_update_btn_check_on_holo_light.png │ │ ├── bmob_update_btn_check_on_pressed_holo_light.png │ │ ├── bmob_update_close_bg_normal.png │ │ └── bmob_update_close_bg_tap.png │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bmob_update_button_cancel_bg_focused.xml │ │ ├── bmob_update_button_cancel_bg_normal.xml │ │ ├── bmob_update_button_cancel_bg_selector.xml │ │ ├── bmob_update_button_cancel_bg_tap.xml │ │ ├── bmob_update_button_check_selector.xml │ │ ├── bmob_update_button_close_bg_selector.xml │ │ ├── bmob_update_button_ok_bg_focused.xml │ │ ├── bmob_update_button_ok_bg_normal.xml │ │ ├── bmob_update_button_ok_bg_selector.xml │ │ ├── bmob_update_button_ok_bg_tap.xml │ │ ├── bmob_update_dialog_bg.xml │ │ ├── bmob_update_wifi_disable.png │ │ ├── ic_launcher_background.xml │ │ └── submit_selector.xml │ │ ├── layout │ │ ├── activity_about.xml │ │ ├── activity_ad.xml │ │ ├── activity_feedback.xml │ │ ├── activity_help.xml │ │ ├── activity_main.xml │ │ └── bmob_update_dialog.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ ├── wechatc.jpg │ │ └── wx_donate.jpg │ │ ├── values │ │ ├── arrays.xml │ │ ├── bmob_common_strings.xml │ │ ├── bmob_update_string.xml │ │ ├── colors.xml │ │ ├── ic_launcher_background.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── file_paths.xml │ │ ├── pref_headers.xml │ │ ├── pref_mhzs.xml │ │ ├── pref_mhzs_ad.xml │ │ ├── pref_mhzs_exp.xml │ │ └── pref_mhzs_tab.xml │ └── test │ └── java │ └── com │ └── lhy │ └── xposed │ └── mhzs │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── img └── share.gif ├── lucky.jpg ├── settings.gradle └── wechatc.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | /.idea 13 | DEV.md 14 | mhzs.zip 15 | /app/release -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/dictionaries/.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 31 | 32 | 33 | 34 | 35 | 36 | 38 | 39 | 40 | 44 | 45 | 49 | 50 | 54 | 55 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 1595901624 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 麻花助手(Xposed Plugin) 已停更 2 | 3 | 麻花助手,这是一款Xposed插件,旨在净化麻花影视手机版/贝贝影视手机版。当前是功能还不是很完善,使用软件时注意**助手所支持的麻花影视 4 | 版本**,现已**支持 EdXposed 框架**,**支持太极(TaiChi)框架**。 5 | 目前插件在逍遥安卓模拟器4.4/5.1/7.1下,均测试成功。 6 | 7 | 收到很多热心的用户赞助,我在这里感谢大家对我的支持和信任。**还有非常感谢这位热心老哥[`Czy492`](https://github.com/Czy492)一直在帮我适配太极(Tai-Chi)**。 8 | 与此同时,我也收到了很多用户对插件兼容性较差的反馈和增加功能的反馈,当然由于Android设备的开源和国产的ROM太多,有些兼容性问题可能会永远无法解决,但是我会尽力而为。 9 | 收到最多反馈的就是太极框架(Tai-Chi)了,这也是我最头痛的问题,这可能是由于太极框架兼容性的原因。 10 | 11 | **目前收到最多反馈的是,部分设备安装助手后任务消失,该问题的解决办法是,先在助手中关闭插件,然后正常启动“麻花影视”,打开任务页面正常显示后,再重新开启助手即可。** 12 | 13 | ## 功能特性 14 | 15 | 麻花助手目前拥有以下功能 [目前支持最新2.7.0版本] 16 | 17 | 1. 支持 EdXposed 框架,太极(TaiChi)框架 18 | 2. 去除启动页广告 19 | 3. 去除启动页5s倒计时 20 | 4. 去除启动页历史广告显示 21 | 5. 去除“推荐”、“电影”、“电视剧”页面中存在的广告 22 | 6. 去除视频播放页面的广告 23 | 7. 自定义主界面底部选项卡 24 | 8. 去除主界面升级提示 25 | 9. 获取视频播放地址(测试) 26 | 10. ~~去除底部滚动广告(测试)~~ 27 | 11. 免特权投屏(测试) 28 | 12. 强制微信分享成功(测试) 29 | 13. 自动签到(测试) 30 | 14. 观看视频时长30分钟+(测试) 31 | 15. 假装分享(测试) 32 | 33 | ## 功能截图 34 | 35 | * 假装分享 36 | 37 |
38 | 39 |
40 | 41 | ## 版本对应 42 | 43 | * 麻花影视 2.6.1——麻花影视助手 0.1 - 0.6.12 44 | * 麻花影视 2.7.0/贝贝影视2.7.0——麻花影视助手 0.7.0 45 | 46 | ## 使用帮助 47 | 48 | **麻花助手**首次运行时,在 Android6.0 + 的设备上需要申请读写SD卡权限,请给予其权限。 49 | 目前**麻花助手**还处于测试期间,功能还不是很完善,在部分设备上运行可能会出现问题。 50 | 首次运行**麻花助手**模块,请重新启动手机(Xposed模块需要)。当然软件已经开源, 51 | 如果您是开发者,您可以定制您需要的功能。部分功能介绍如下: 52 | 53 | 1. “**全局设置**”——您可以选择是否启用插件,如果此选项为“否”,那么所有的功能都将会禁用 54 | 2. “**详细设置**”——目前包含“**广告净化**”,“**底部栏设置**”,“**去除5s启动**”三个设置 55 | 3. “**广告净化**”——可以自定义广告净化 56 | 4. “**底部栏设置**”——可以自定义首页底部五个选项卡的显示与隐藏 57 | 5. “**去除5s启动**”——开启后,可自动进入首页; 58 | 6. “**实验性功能**”——在此选项内的所有功能都是测试功能,在某些设备上可能会无效,希望大家多多反馈此选项下的功能 59 | 7. “**获取视频地址**”——该功能尚处于测试阶段。开启后,将会在视频播放页面添加四个按钮,分别是360P,480P,720P,1080P,点击即可自动复制到剪切板。 60 | 如果没有蓝光特权,则将无法获取到1080P地址。获取到的视频地址是**.m3u8格式**,播放链接的时效性仅有几小时且直接复制到浏览器无法播放, 61 | 请使用视频播放器或者是m3u8视频解析链接播放。**如果播放时一直是0KB/s,请复制该链接至站外或者电脑上播放** 62 | 8. “**强制微信分享成功**”——**该功能将会“假装分享”取代**。被该功能是有部分用户反馈在太极(Tai-Chi)下无法分享成功而开发的。该模块启用后,通过微信分享到群或者朋友圈, 63 | 无论分享成功与失败,都会返回成功状态。**提示:可在模拟器下使用(下载微信后无须登录微信),分享后立即返回即可** 64 | 9. “**免特权投屏**”——该功能是测试功能,可能会无效,如果无效希望大家反馈问题。 65 | 10. “**自动签到**”——该功能可以说是半自动签到,只有当用户登录后,点击到任务页面,才会自动签到。 66 | 11. “**观看视频30分钟+**”——开启该功能后,播放任意视频即可完成观影30分钟的任务。 67 | 12. “**假装分享**”——此功能仅可以在麻花影视和贝贝影视中使用。此功能开启后,由于优先级较高,将会覆盖“强制微信分享成功”,如果您的设备测试此功能没有问题,则请您关闭“强制微信分享成功”功能,该功能后期将会取代“强制微信分享成功”。支持微信朋友圈、微信、QQ、QQ空间、微博分享,点击分享不会跳转APP,也不会提示分享成功,但是状态时成功的。本功能可以用来获取热门视频播放和完成分享任务。 68 | 69 | 注:目前助手没有检查更新功能,大家可以从Github或者蓝奏云下载最新版本(地址在下方)。 70 | 71 | ## 问题反馈 72 | * 应用内反馈 73 | * 提交 issue 74 | * 发邮件至 haoyu3@163.com ,邮件主题注明“**麻花助手+版本号+框架名称**” 75 | 76 | ## Wiki 77 | 78 | * [码云](https://gitee.com/haoyu3/mhzs) 79 | * [开发进度](https://github.com/1595901624/mhzs/wiki/开发进度) 80 | * [扩展插件](https://github.com/1595901624/mhzs/wiki/扩展插件) 81 | * [更新日志](https://github.com/1595901624/mhzs/wiki/更新日志) 82 | * [Github下载地址](https://github.com/1595901624/mhzs/releases) 83 | * [蓝奏云下载地址](https://www.lanzous.com/b614986/) 密码:4uk6 84 | 85 | 86 | ## 捐赠与致谢 87 | 88 | ##### 捐赠名单 89 | 90 | 91 | **`*建鑫` ¥20.00** 92 | **`*明伟` ¥10.00** 93 | **`*学林` ¥10.00** 94 | **`*飞` ¥05.00** 95 | **`*润泽` ¥04.84** 96 | **`*思源` ¥04.00** 97 | **`*哲涵` ¥03.00** 98 | **`*堃` ¥02.00** 99 | **`*帅帅` ¥02.00** 100 | **`*钦` ¥01.10** 101 | **`*明峰` ¥01.00** 102 | **`*威` ¥01.00** 103 | **`*友定` ¥01.00** 104 | **`*松` ¥00.45** 105 | **`*羽` ¥00.38** 106 | **`*成` ¥00.10** 107 | **`*福常` ¥00.10** 108 | **`*凯` ¥00.10** 109 | **`*学` ¥00.10** 110 | **`*帅` ¥00.10** 111 | **`*源` ¥00.07** 112 | **`*炳亮` ¥00.01** 113 | **`*佳旺` ¥00.01** 114 | 115 | 非常感谢你们的捐助,感谢你们对我的支持!(以上名单按起始汉字首字母辅助排序) 116 | 117 | ##### 致谢名单 118 | 119 | **[`a2212997715`](https://github.com/a2212997715)**、**`晓星`**、**[`Czy492`](https://github.com/Czy492)**、**[`AceMONKEY519`](https://github.com/AceMONKEY519)** 120 | 121 | ##### 捐赠二维码 122 | 123 | **推荐通过扫码领红包的方式捐赠哟** 124 | 125 |
126 | 127 |   128 | 129 | 130 | 131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /alipayc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/alipayc.jpg -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /release 3 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.lhy.xposed.mhzs" 7 | minSdkVersion 17 8 | targetSdkVersion 27 9 | versionCode 1109 10 | versionName "0.7.1 Beta" 11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(include: ['*.jar'], dir: 'libs') 23 | implementation 'androidx.appcompat:appcompat:1.1.0-alpha02' 24 | implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'androidx.test:runner:1.1.2-alpha01' 27 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.2-alpha01' 28 | implementation 'com.google.code.gson:gson:2.8.5' 29 | implementation 'androidx.preference:preference:1.1.0-alpha03' 30 | implementation 'com.github.didikee:AndroidDonate:0.1.0' 31 | compileOnly 'de.robv.android.xposed:api:82' 32 | compileOnly 'de.robv.android.xposed:api:82:sources' 33 | implementation 'com.vladsch.flexmark:flexmark:0.40.22' 34 | implementation 'com.vladsch.flexmark:flexmark-util:0.40.22' 35 | implementation 'com.vladsch.flexmark:flexmark-ext-tables:0.40.22' 36 | implementation 'com.vladsch.flexmark:flexmark-profile-pegdown:0.40.22' 37 | implementation 'com.squareup.okhttp3:okhttp:3.12.1' 38 | implementation 'cn.bmob.android:bmob-sdk:3.7.0' 39 | implementation "io.reactivex.rxjava2:rxjava:2.2.2" 40 | implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' 41 | implementation 'com.squareup.okio:okio:2.1.0' 42 | } 43 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/lhy/xposed/mhzs/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs; 2 | 3 | import android.content.Context; 4 | import androidx.test.InstrumentationRegistry; 5 | import androidx.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.lhy.xposed.pref_mhzs", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 30 | 33 | 36 | 39 | 40 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 52 | 55 | 58 | 61 | 64 | 67 | 68 | 71 | 76 | 79 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /app/src/main/assets/help.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 使用帮助 8 | 9 | 10 |

麻花助手

11 | 12 |

麻花助手,这是一款Xposed插件,旨在净化麻花影视手机版。当前是助手功能还不是很完善,可能部分设备有些问题,使用软件时注意助手所支持的麻花影视 13 | 版本支持 Edxposed 框架,支持太极(Tai-Chi)框架。

14 | 15 |

版本特点

16 | 17 | 34 | 35 |

如何安装

36 | 37 |

软件运行需要 Xposed 环境,请安装 Xposed 框架后,在 Xposed 38 | 中启用该框架。

39 | 40 |

使用帮助

41 | 42 |

麻花助手首次运行时,在 Android6.0 + 的设备上需要申请读写SD卡权限,请给予其权限。 43 | 目前麻花助手还处于测试期间,功能还不是很完善,在部分设备上运行可能会出现问题。 44 | 首次运行麻花助手模块,请重新启动手机(Xposed模块需要)。当然软件已经开源, 45 | 如果您是开发者,您可以定制您需要的功能。部分功能介绍如下:

46 | 47 |
    48 |
  1. 在“全局设置”中,您可以选择是否启用插件,如果此选项为“否”,那么所有的功能都将会禁用;
  2. 49 |
  3. 在“详细设置”中目前包含“广告净化”,“底部栏设置”,“去除5s启动”三个设置; 50 |
  4. 51 |
  5. 在“广告净化”中,可以自定义广告净化;
  6. 52 |
  7. 在“底部栏设置”中,可以自定义首页底部五个选项卡的显示与隐藏;
  8. 53 |
  9. 去除5s启动”开启后,可自动进入首页;
  10. 54 |
  11. 去除更新”开启后,主界面升级提示将不会出现;
  12. 55 |
  13. 获取视频地址”该功能尚处于测试阶段。开启后,将会在视频播放页面添加四个按钮,分别是360P,480P,720P,1080P, 56 | 点击按钮即可将连接复制到剪切板。如果没有蓝光特权,则将无法获取到1080P地址。获取到的视频地址是.m3u8格式,播放链接的时效性仅有几小时且直接复制到浏览器无法播放, 57 | 请使用视频播放器或者是m3u8视频解析链接播放。如果播放时一直是0KB/s,请复制该链接至站外播放。
  14. 58 | 59 | 60 | 61 |
62 | 63 |

问题反馈

64 | 65 | 69 | 70 |

捐赠名单

71 | 75 | 76 |

致谢

77 | 78 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.lhy.xposed.mhzs.HookLoader -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/HookLoader.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs; 2 | 3 | import com.lhy.xposed.mhzs.helper.Config; 4 | import com.lhy.xposed.mhzs.helper.Constant; 5 | import com.lhy.xposed.mhzs.helper.LogUtil; 6 | 7 | import java.io.File; 8 | import java.lang.reflect.Method; 9 | 10 | import dalvik.system.PathClassLoader; 11 | import de.robv.android.xposed.IXposedHookLoadPackage; 12 | import de.robv.android.xposed.XposedBridge; 13 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 14 | 15 | 16 | public class HookLoader implements IXposedHookLoadPackage { 17 | 18 | @Override 19 | public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable { 20 | if (!Config.HOOK_APPLICATION_PACKAGE_NAME.contains(loadPackageParam.packageName)) 21 | return; 22 | 23 | // TODO: 2019/3/14 0014 检查模块运行状态3/3 24 | // hookModuleActive(loadPackageParam); 25 | 26 | try { 27 | //在发布时,直接调用即可。 28 | if (!BuildConfig.DEBUG) { 29 | HookMain hookMain = new HookMain(); 30 | hookMain.handleLoadPackage4release(loadPackageParam); 31 | return; 32 | } 33 | //在调试模式为了不频繁重启,使用反射的方式调用自身的指定函数。 34 | 35 | /*【方法2】*/ 36 | final String packageName = HookMain.class.getPackage().getName(); 37 | String filePath = String.format("/data/app/%s-%s.apk", packageName, 1); 38 | if (!new File(filePath).exists()) { 39 | filePath = String.format("/data/app/%s-%s.apk", packageName, 2); 40 | if (!new File(filePath).exists()) { 41 | filePath = String.format("/data/app/%s-%s/base.apk", packageName, 1); 42 | if (!new File(filePath).exists()) { 43 | filePath = String.format("/data/app/%s-%s/base.apk", packageName, 2); 44 | if (!new File(filePath).exists()) { 45 | XposedBridge.log("Error:在/data/app找不到APK文件" + packageName); 46 | return; 47 | } 48 | } 49 | } 50 | } 51 | 52 | final PathClassLoader pathClassLoader = new PathClassLoader(filePath, ClassLoader.getSystemClassLoader()); 53 | final Class aClass = Class.forName(packageName + "." + HookMain.class.getSimpleName(), true, pathClassLoader); 54 | final Method aClassMethod = aClass.getMethod("handleLoadPackage4release", XC_LoadPackage.LoadPackageParam.class); 55 | aClassMethod.invoke(aClass.newInstance(), loadPackageParam); 56 | } catch (final Exception e) { 57 | XposedBridge.log(e); 58 | } 59 | } 60 | 61 | /** 62 | * 暂时不应用 63 | * 64 | * @param lpparam 65 | */ 66 | // private void hookModuleActive(XC_LoadPackage.LoadPackageParam lpparam) { 67 | // if (lpparam.packageName.equals(BuildConfig.APPLICATION_ID)) { 68 | // XposedHelpers.findAndHookMethod(SettingFragment.class.getName(), lpparam.classLoader, "isModuleActive", XC_MethodReplacement.returnConstant(true)); 69 | // } 70 | // } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/HookMain.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs; 2 | 3 | import android.content.Context; 4 | 5 | import com.lhy.xposed.mhzs.helper.Constant; 6 | import com.lhy.xposed.mhzs.helper.LogUtil; 7 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 8 | import com.lhy.xposed.mhzs.plugin.AutoSignPlugin; 9 | import com.lhy.xposed.mhzs.plugin.ClearBootAdPlugin; 10 | import com.lhy.xposed.mhzs.plugin.ClearDanmuPlugin; 11 | import com.lhy.xposed.mhzs.plugin.ClearFiveSecondsPlugin; 12 | import com.lhy.xposed.mhzs.plugin.ClearMainAdPlugin; 13 | import com.lhy.xposed.mhzs.plugin.ClearMyFragmentAdPlugin; 14 | import com.lhy.xposed.mhzs.plugin.ClearPlayerAdPlugin; 15 | import com.lhy.xposed.mhzs.plugin.CustomMainInterfacePlugin; 16 | import com.lhy.xposed.mhzs.plugin.HideDanmuPlugin; 17 | import com.lhy.xposed.mhzs.plugin.IPlugin; 18 | import com.lhy.xposed.mhzs.plugin.NoUpdatePlugin; 19 | import com.lhy.xposed.mhzs.plugin.SharePlugin; 20 | import com.lhy.xposed.mhzs.plugin.TVPlugin; 21 | import com.lhy.xposed.mhzs.plugin.VideoURLPlugin; 22 | import com.lhy.xposed.mhzs.plugin.WatchThirtyMinutesPlugin; 23 | import com.lhy.xposed.mhzs.plugin.WechatSharePlugin; 24 | 25 | import de.robv.android.xposed.XC_MethodHook; 26 | import de.robv.android.xposed.XposedHelpers; 27 | import de.robv.android.xposed.callbacks.XC_LoadPackage; 28 | 29 | 30 | public class HookMain { 31 | private IPlugin[] iPlugins = new IPlugin[]{ 32 | new ClearFiveSecondsPlugin(), 33 | new ClearBootAdPlugin(), 34 | new ClearMainAdPlugin(), 35 | new ClearPlayerAdPlugin(), 36 | new VideoURLPlugin(), 37 | new CustomMainInterfacePlugin(), 38 | new NoUpdatePlugin(), 39 | new TVPlugin(), 40 | new AutoSignPlugin(), 41 | new WatchThirtyMinutesPlugin(), 42 | new WechatSharePlugin(), 43 | new SharePlugin(), 44 | new ClearMyFragmentAdPlugin(), 45 | new ClearDanmuPlugin(), 46 | new HideDanmuPlugin() 47 | }; 48 | 49 | /** 50 | * 主函数 51 | * 52 | * @param param 53 | * @throws Throwable 54 | */ 55 | public void main(XC_MethodHook.MethodHookParam param) throws Throwable { 56 | if (!XPrefUtils.getPref().getBoolean("global_set", true)) { 57 | LogUtil.e("Plugin is close!"); 58 | return; 59 | } 60 | 61 | LogUtil.e("Plugin is open!"); 62 | Context context = (Context) param.args[0]; 63 | final ClassLoader classLoader = context.getClassLoader(); 64 | 65 | 66 | //进入麻花领空,运行插件 67 | for (IPlugin iPlugin : iPlugins) { 68 | if (iPlugin.isOpen()) 69 | iPlugin.run(classLoader); 70 | } 71 | } 72 | 73 | public void handleLoadPackage4release(final XC_LoadPackage.LoadPackageParam loadPackageParam) { 74 | XposedHelpers.findAndHookMethod("com.stub.StubApp", loadPackageParam.classLoader, 75 | "attachBaseContext", Context.class, new XC_MethodHook() { 76 | @Override 77 | protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { 78 | /** 79 | * 获取360加固的CLASSLOADER 80 | * 81 | */ 82 | Constant.CURRENT_HOOK_PACKAGE_NAME = loadPackageParam.packageName; 83 | LogUtil.e("PACKAGE_NAME" + Constant.CURRENT_HOOK_PACKAGE_NAME); 84 | //主函数 85 | main(param); 86 | } 87 | }); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/MHApplicaiton.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs; 2 | 3 | import android.app.Application; 4 | 5 | import cn.bmob.v3.Bmob; 6 | 7 | public class MHApplicaiton extends Application { 8 | 9 | @Override 10 | public void onCreate() { 11 | super.onCreate(); 12 | Bmob.initialize(this, "0053ab880ceb939700414994235c4adf"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.text.SpannableString; 7 | import android.text.Spanned; 8 | import android.text.style.ForegroundColorSpan; 9 | import android.view.MenuItem; 10 | import android.view.View; 11 | import android.widget.TextView; 12 | 13 | import com.lhy.xposed.mhzs.R; 14 | import com.lhy.xposed.mhzs.helper.Config; 15 | import com.lhy.xposed.mhzs.helper.HYHelper; 16 | 17 | import androidx.appcompat.app.AppCompatActivity; 18 | import androidx.appcompat.widget.Toolbar; 19 | import androidx.core.content.ContextCompat; 20 | import cn.bmob.v3.update.BmobUpdateAgent; 21 | 22 | public class AboutActivity extends AppCompatActivity implements View.OnClickListener { 23 | private Toolbar mToolbar; 24 | private TextView versionTextView; 25 | private TextView supportVersionText; 26 | private TextView supportBBVersionText; 27 | private TextView feedbackTextView; 28 | private TextView updateTextView; 29 | private TextView githubTextView; 30 | private boolean isAboutActivity = false; 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | initView(); 36 | initData(); 37 | } 38 | 39 | private void initData() { 40 | isAboutActivity = true; 41 | ForegroundColorSpan colorSpan = new ForegroundColorSpan(ContextCompat.getColor(this, R.color.colorAccent)); 42 | 43 | SpannableString spannableString = new SpannableString("麻花助手当前版本:" + HYHelper.getVerisonName(this)); 44 | spannableString.setSpan(colorSpan, 9, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 45 | versionTextView.setText(spannableString); 46 | 47 | SpannableString spannableString2 = new SpannableString("支持麻花影视版本:" + Config.SUPPORT_MHYS_VERISON); 48 | spannableString2.setSpan(colorSpan, 9, spannableString2.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 49 | supportVersionText.setText(spannableString2); 50 | 51 | SpannableString spannableString3 = new SpannableString("支持贝贝影视版本:" + Config.SUPPORT_MHYS_VERISON); 52 | spannableString3.setSpan(colorSpan, 9, spannableString3.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 53 | supportBBVersionText.setText(spannableString3); 54 | } 55 | 56 | private void initView() { 57 | setContentView(R.layout.activity_about); 58 | mToolbar = findViewById(R.id.toolbar_about); 59 | versionTextView = findViewById(R.id.about_current_version); 60 | supportVersionText = findViewById(R.id.about_mh_version); 61 | supportBBVersionText = findViewById(R.id.about_bb_version); 62 | feedbackTextView = findViewById(R.id.about_feedback); 63 | updateTextView = findViewById(R.id.about_update); 64 | githubTextView = findViewById(R.id.about_github); 65 | 66 | feedbackTextView.setOnClickListener(this); 67 | updateTextView.setOnClickListener(this); 68 | githubTextView.setOnClickListener(this); 69 | 70 | mToolbar.setTitle("关于"); 71 | setSupportActionBar(mToolbar); 72 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 73 | } 74 | 75 | private void checkUpdate() { 76 | //发起自动更新 77 | BmobUpdateAgent.forceUpdate(AboutActivity.this); 78 | } 79 | 80 | @Override 81 | public boolean onOptionsItemSelected(MenuItem item) { 82 | if (item.getItemId() == android.R.id.home) { 83 | onBackPressed(); 84 | return true; 85 | } 86 | return super.onOptionsItemSelected(item); 87 | } 88 | 89 | @Override 90 | public void onClick(View view) { 91 | switch (view.getId()) { 92 | case R.id.about_feedback: 93 | startActivity(new Intent(this, FeedbackActivity.class)); 94 | break; 95 | case R.id.about_update: 96 | checkUpdate(); 97 | break; 98 | case R.id.about_github: 99 | startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/1595901624/mhzs"))); 100 | break; 101 | default: 102 | break; 103 | } 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/AdSettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.graphics.Color; 4 | import android.view.MenuItem; 5 | 6 | import com.lhy.xposed.mhzs.fragment.AdSettingFragment; 7 | 8 | import androidx.appcompat.widget.Toolbar; 9 | 10 | public class AdSettingActivity extends BaseActivity { 11 | @Override 12 | protected void initToolbar(Toolbar mToolbar) { 13 | mToolbar.setTitle("广告净化"); 14 | mToolbar.setTitleTextColor(Color.WHITE); 15 | setSupportActionBar(mToolbar); 16 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 17 | } 18 | 19 | @Override 20 | protected void initView() { 21 | 22 | } 23 | 24 | @Override 25 | protected void initData() { 26 | switchFragment(new AdSettingFragment()); 27 | } 28 | 29 | @Override 30 | public boolean onOptionsItemSelected(MenuItem item) { 31 | if(item.getItemId() == android.R.id.home){ 32 | onBackPressed(); 33 | return true; 34 | } 35 | return super.onOptionsItemSelected(item); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/AppCompatPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | /* 4 | * Copyright (C) 2014 The Android Open Source Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.content.res.Configuration; 20 | import android.os.Bundle; 21 | import android.preference.PreferenceActivity; 22 | import androidx.annotation.LayoutRes; 23 | import androidx.annotation.Nullable; 24 | import androidx.appcompat.app.ActionBar; 25 | import androidx.appcompat.app.AppCompatDelegate; 26 | import androidx.appcompat.widget.Toolbar; 27 | import android.view.MenuInflater; 28 | import android.view.View; 29 | import android.view.ViewGroup; 30 | 31 | /** 32 | * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls 33 | * to be used with AppCompat. 34 | *

35 | * This technique can be used with an {@link android.app.Activity} class, not just 36 | * {@link android.preference.PreferenceActivity}. 37 | */ 38 | public abstract class AppCompatPreferenceActivity extends PreferenceActivity { 39 | private AppCompatDelegate mDelegate; 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | getDelegate().installViewFactory(); 44 | getDelegate().onCreate(savedInstanceState); 45 | super.onCreate(savedInstanceState); 46 | } 47 | 48 | @Override 49 | protected void onPostCreate(Bundle savedInstanceState) { 50 | super.onPostCreate(savedInstanceState); 51 | getDelegate().onPostCreate(savedInstanceState); 52 | } 53 | 54 | public ActionBar getSupportActionBar() { 55 | return getDelegate().getSupportActionBar(); 56 | } 57 | 58 | public void setSupportActionBar(@Nullable Toolbar toolbar) { 59 | getDelegate().setSupportActionBar(toolbar); 60 | } 61 | 62 | @Override 63 | public MenuInflater getMenuInflater() { 64 | return getDelegate().getMenuInflater(); 65 | } 66 | 67 | @Override 68 | public void setContentView(@LayoutRes int layoutResID) { 69 | getDelegate().setContentView(layoutResID); 70 | } 71 | 72 | @Override 73 | public void setContentView(View view) { 74 | getDelegate().setContentView(view); 75 | } 76 | 77 | @Override 78 | public void setContentView(View view, ViewGroup.LayoutParams params) { 79 | getDelegate().setContentView(view, params); 80 | } 81 | 82 | @Override 83 | public void addContentView(View view, ViewGroup.LayoutParams params) { 84 | getDelegate().addContentView(view, params); 85 | } 86 | 87 | @Override 88 | protected void onPostResume() { 89 | super.onPostResume(); 90 | getDelegate().onPostResume(); 91 | } 92 | 93 | @Override 94 | protected void onTitleChanged(CharSequence title, int color) { 95 | super.onTitleChanged(title, color); 96 | getDelegate().setTitle(title); 97 | } 98 | 99 | @Override 100 | public void onConfigurationChanged(Configuration newConfig) { 101 | super.onConfigurationChanged(newConfig); 102 | getDelegate().onConfigurationChanged(newConfig); 103 | } 104 | 105 | @Override 106 | protected void onStop() { 107 | super.onStop(); 108 | getDelegate().onStop(); 109 | } 110 | 111 | @Override 112 | protected void onDestroy() { 113 | super.onDestroy(); 114 | getDelegate().onDestroy(); 115 | } 116 | 117 | public void invalidateOptionsMenu() { 118 | getDelegate().invalidateOptionsMenu(); 119 | } 120 | 121 | private AppCompatDelegate getDelegate() { 122 | if (mDelegate == null) { 123 | mDelegate = AppCompatDelegate.create(this, null); 124 | } 125 | return mDelegate; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.ContentResolver; 5 | import android.net.Uri; 6 | import android.os.Bundle; 7 | import android.util.Log; 8 | import android.view.MenuItem; 9 | 10 | import com.lhy.xposed.mhzs.R; 11 | import com.lhy.xposed.mhzs.helper.FileUtils; 12 | 13 | import java.io.File; 14 | 15 | import androidx.annotation.Nullable; 16 | import androidx.appcompat.app.AppCompatActivity; 17 | import androidx.appcompat.widget.Toolbar; 18 | import androidx.fragment.app.Fragment; 19 | import androidx.fragment.app.FragmentTransaction; 20 | 21 | public abstract class BaseActivity extends AppCompatActivity { 22 | private FragmentTransaction fragmentTransaction; 23 | private Fragment currentFragment; 24 | private Toolbar mToolbar; 25 | 26 | @Override 27 | public void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_main); 30 | mToolbar = findViewById(R.id.toolbar); 31 | initToolbar(mToolbar); 32 | initView(); 33 | initData(); 34 | } 35 | 36 | protected abstract void initToolbar(Toolbar mToolbar); 37 | 38 | protected abstract void initView(); 39 | 40 | protected abstract void initData(); 41 | 42 | 43 | protected void switchFragment(Fragment targetFragment) { 44 | fragmentTransaction = getSupportFragmentManager().beginTransaction(); 45 | if (!targetFragment.isAdded()) { 46 | if (currentFragment != null) { 47 | fragmentTransaction.hide(currentFragment); 48 | } 49 | fragmentTransaction.add(R.id.container, targetFragment) 50 | .commit(); 51 | } else { 52 | fragmentTransaction.hide(currentFragment) 53 | .show(targetFragment) 54 | .commit(); 55 | } 56 | //更改当前的fragment所指向的值 57 | currentFragment = targetFragment; 58 | } 59 | 60 | @Override 61 | protected void onDestroy() { 62 | super.onDestroy(); 63 | setWorldReadable(); 64 | } 65 | 66 | @Override 67 | protected void onPause() { 68 | super.onPause(); 69 | setWorldReadable(); 70 | } 71 | 72 | /** 73 | * 设置Pref为可读 74 | */ 75 | @SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) 76 | @SuppressLint({"SetWorldReadable", "WorldReadableFiles"}) 77 | public void setWorldReadable() { 78 | if (FileUtils.getDefaultPrefFile(this) 79 | .exists()) { 80 | for (File file : new File[]{FileUtils.getDataDir(this), FileUtils.getPrefDir(this), FileUtils.getDefaultPrefFile(this)}) { 81 | file.setReadable(true, false); 82 | file.setExecutable(true, false); 83 | } 84 | } 85 | } 86 | 87 | 88 | /************************************************************* 89 | * EXP/VXP SUPPORT START 90 | * ***********************************************************/ 91 | 92 | protected boolean isModuleActive() { 93 | // VirtualXposed 在某些机型上hook短方法有问题,这里认为添加日志增大方法长度确保能hook成功。 94 | Log.i("fake", "isModuleActive"); 95 | return false; 96 | } 97 | 98 | protected boolean isExpModuleActive() { 99 | boolean isActive = false; 100 | try { 101 | ContentResolver contentResolver = getContentResolver(); 102 | Uri uri = Uri.parse("content://me.weishu.exposed.CP/"); 103 | Bundle result = contentResolver.call(uri, "active", null, null); 104 | if (result == null) { 105 | return false; 106 | } 107 | isActive = result.getBoolean("active", false); 108 | } catch (Exception e) { 109 | e.printStackTrace(); 110 | } 111 | return isActive; 112 | } 113 | 114 | /************************************************************* 115 | * EXP/VXP SUPPORT END 116 | * ***********************************************************/ 117 | 118 | @Override 119 | public boolean onOptionsItemSelected(MenuItem item) { 120 | if(item.getItemId() == android.R.id.home){ 121 | onBackPressed(); 122 | return true; 123 | } 124 | return super.onOptionsItemSelected(item); 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/ExpSettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.graphics.Color; 4 | 5 | import com.lhy.xposed.mhzs.fragment.ExpSettingFragment; 6 | 7 | import androidx.appcompat.widget.Toolbar; 8 | 9 | public class ExpSettingActivity extends BaseActivity { 10 | @Override 11 | protected void initToolbar(Toolbar mToolbar) { 12 | mToolbar.setTitle("实验性功能"); 13 | mToolbar.setTitleTextColor(Color.WHITE); 14 | setSupportActionBar(mToolbar); 15 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 16 | } 17 | 18 | @Override 19 | protected void initView() { 20 | 21 | } 22 | 23 | @Override 24 | protected void initData() { 25 | switchFragment(new ExpSettingFragment()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/FeedbackActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import androidx.appcompat.widget.Toolbar; 5 | import cn.bmob.v3.exception.BmobException; 6 | import cn.bmob.v3.listener.SaveListener; 7 | 8 | import android.os.Bundle; 9 | import android.text.TextUtils; 10 | import android.view.MenuItem; 11 | import android.view.View; 12 | import android.widget.AdapterView; 13 | import android.widget.Button; 14 | import android.widget.EditText; 15 | import android.widget.Spinner; 16 | 17 | import com.lhy.xposed.mhzs.R; 18 | import com.lhy.xposed.mhzs.bean.Feedback; 19 | import com.lhy.xposed.mhzs.helper.HYHelper; 20 | import com.lhy.xposed.mhzs.helper.ToastUtils; 21 | 22 | public class FeedbackActivity extends AppCompatActivity implements View.OnClickListener { 23 | private Toolbar mToolbar; 24 | private EditText detailEditText; 25 | private EditText contactEditText; 26 | private Spinner mSpinner; 27 | private Button submitBtn; 28 | 29 | private String currentSpinnerName; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | initView(); 35 | } 36 | 37 | private void submitFeedback() { 38 | String detail = detailEditText.getText().toString(); 39 | String contact = contactEditText.getText().toString(); 40 | 41 | if (TextUtils.isEmpty(detail.trim())) { 42 | ToastUtils.toast(this, "请输入问题详细描述!"); 43 | return; 44 | } 45 | 46 | if (TextUtils.isEmpty(contact.trim())) { 47 | contact = "未知"; 48 | } 49 | 50 | Feedback feedback = new Feedback(); 51 | feedback.setContact(contact); 52 | feedback.setDetail(detail); 53 | feedback.setFramework(currentSpinnerName); 54 | feedback.setDevice(HYHelper.getDeviceInfo()); 55 | feedback.setVersion(HYHelper.getVerisonName(this)); 56 | feedback.save(new SaveListener() { 57 | @Override 58 | public void done(String s, BmobException e) { 59 | if (e == null) { 60 | ToastUtils.toast(FeedbackActivity.this, "感谢您的反馈!"); 61 | FeedbackActivity.this.finish(); 62 | } else { 63 | ToastUtils.toast(FeedbackActivity.this, "提交失败,请检查网络!"); 64 | } 65 | } 66 | }); 67 | 68 | } 69 | 70 | private void initView() { 71 | setContentView(R.layout.activity_feedback); 72 | mToolbar = findViewById(R.id.toolbar_feedback); 73 | detailEditText = findViewById(R.id.feedback_detail); 74 | contactEditText = findViewById(R.id.feedback_contact); 75 | mSpinner = findViewById(R.id.spinner_framework); 76 | submitBtn = findViewById(R.id.feedback_submit); 77 | submitBtn.setOnClickListener(this); 78 | 79 | final String[] values = getResources().getStringArray(R.array.framework); 80 | mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 81 | @Override 82 | public void onItemSelected(AdapterView adapterView, View view, int i, long l) { 83 | currentSpinnerName = values[i]; 84 | } 85 | 86 | @Override 87 | public void onNothingSelected(AdapterView adapterView) { 88 | 89 | } 90 | }); 91 | 92 | mToolbar.setTitle("反馈"); 93 | setSupportActionBar(mToolbar); 94 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 95 | 96 | } 97 | 98 | @Override 99 | public boolean onOptionsItemSelected(MenuItem item) { 100 | if (item.getItemId() == android.R.id.home) { 101 | onBackPressed(); 102 | return true; 103 | } 104 | return super.onOptionsItemSelected(item); 105 | } 106 | 107 | @Override 108 | public void onClick(View view) { 109 | switch (view.getId()) { 110 | case R.id.feedback_submit: 111 | submitFeedback(); 112 | break; 113 | default: 114 | break; 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/HelpActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | import androidx.appcompat.widget.Toolbar; 5 | import okhttp3.Call; 6 | import okhttp3.Callback; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | 11 | import android.app.ProgressDialog; 12 | import android.os.Bundle; 13 | import android.os.Handler; 14 | import android.os.Message; 15 | import android.view.MenuItem; 16 | import android.view.View; 17 | import android.webkit.WebView; 18 | import android.widget.ProgressBar; 19 | 20 | import com.lhy.xposed.mhzs.R; 21 | import com.lhy.xposed.mhzs.helper.Config; 22 | import com.lhy.xposed.mhzs.helper.HYHelper; 23 | import com.lhy.xposed.mhzs.helper.LogUtil; 24 | import com.lhy.xposed.mhzs.helper.ToastUtils; 25 | import com.vladsch.flexmark.html.HtmlRenderer; 26 | import com.vladsch.flexmark.parser.Parser; 27 | import com.vladsch.flexmark.profiles.pegdown.Extensions; 28 | import com.vladsch.flexmark.profiles.pegdown.PegdownOptionsAdapter; 29 | import com.vladsch.flexmark.util.ast.Node; 30 | import com.vladsch.flexmark.util.options.DataHolder; 31 | 32 | import java.io.IOException; 33 | 34 | public class HelpActivity extends AppCompatActivity { 35 | private ProgressBar progressBar; 36 | private Toolbar mToolbar; 37 | private WebView mWebView; 38 | private final int GET_MARKDOWN_SUCCESS = 0x1; 39 | private final int GET_MARKDOWN_FAILED = 0x0; 40 | 41 | private Handler handler = new Handler() { 42 | @Override 43 | public void handleMessage(Message msg) { 44 | super.handleMessage(msg); 45 | if (msg.what == GET_MARKDOWN_FAILED) { 46 | ToastUtils.toast(HelpActivity.this, "请检查网络是否接通!"); 47 | progressBar.setVisibility(View.GONE); 48 | } else if (msg.what == GET_MARKDOWN_SUCCESS) { 49 | progressBar.setVisibility(View.GONE); 50 | mWebView.setVisibility(View.VISIBLE); 51 | showHtml((String) msg.obj); 52 | } 53 | } 54 | }; 55 | 56 | @Override 57 | protected void onCreate(Bundle savedInstanceState) { 58 | super.onCreate(savedInstanceState); 59 | setContentView(R.layout.activity_help); 60 | mToolbar = findViewById(R.id.toolbar_help); 61 | mWebView = findViewById(R.id.help_web); 62 | progressBar = findViewById(R.id.progress_help); 63 | 64 | mToolbar.setTitle("使用帮助"); 65 | setSupportActionBar(mToolbar); 66 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 67 | 68 | getHelpMarkdown(); 69 | 70 | // mWebView.loadUrl("file:///android_asset/help.html"); 71 | } 72 | 73 | @Override 74 | public boolean onOptionsItemSelected(MenuItem item) { 75 | if (item.getItemId() == android.R.id.home) { 76 | onBackPressed(); 77 | return true; 78 | } 79 | return super.onOptionsItemSelected(item); 80 | } 81 | 82 | /** 83 | * 服务器获取帮助md 84 | */ 85 | public void getHelpMarkdown() { 86 | OkHttpClient okHttpClient = new OkHttpClient(); 87 | Request request = new Request.Builder().get().url(Config.HELP_MARKDOWN_URL).build(); 88 | okHttpClient.newCall(request).enqueue(new Callback() { 89 | @Override 90 | public void onFailure(Call call, IOException e) { 91 | handler.sendEmptyMessage(GET_MARKDOWN_FAILED); 92 | } 93 | 94 | @Override 95 | public void onResponse(Call call, Response response) throws IOException { 96 | Message msg = new Message(); 97 | msg.what = GET_MARKDOWN_SUCCESS; 98 | msg.obj = response.body().string(); 99 | handler.sendMessage(msg); 100 | } 101 | }); 102 | } 103 | 104 | 105 | /** 106 | * 展示网页 107 | */ 108 | private void showHtml(String md) { 109 | DataHolder OPTIONS = PegdownOptionsAdapter.flexmarkOptions(true, 110 | Extensions.NONE); 111 | Parser parser = Parser.builder(OPTIONS).build(); 112 | HtmlRenderer renderer = HtmlRenderer.builder(OPTIONS).build(); 113 | 114 | Node document = parser.parse(md); 115 | String html = renderer.render(document); 116 | 117 | // LogUtil.e(html); 118 | 119 | mWebView.getSettings().setDefaultTextEncodingName("UTF-8"); 120 | mWebView.loadData(html, "text/html; charset=UTF-8", null); 121 | } 122 | 123 | 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.Manifest; 4 | import android.graphics.Color; 5 | 6 | import com.lhy.xposed.mhzs.fragment.SettingFragment; 7 | import com.lhy.xposed.mhzs.helper.ToastUtils; 8 | import com.lhy.xposed.mhzs.permission.PermissionHelper; 9 | import com.lhy.xposed.mhzs.permission.PermissionInterface; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.appcompat.widget.Toolbar; 13 | import cn.bmob.v3.update.BmobUpdateAgent; 14 | 15 | 16 | public class MainActivity extends BaseActivity implements PermissionInterface { 17 | private PermissionHelper mPermissionHelper; 18 | 19 | @Override 20 | protected void initToolbar(Toolbar mToolbar) { 21 | mToolbar.setTitle("麻花影视助手"); 22 | mToolbar.setTitleTextColor(Color.WHITE); 23 | setSupportActionBar(mToolbar); 24 | getSupportActionBar().setDisplayHomeAsUpEnabled(false); 25 | } 26 | 27 | @Override 28 | protected void initView() { 29 | BmobUpdateAgent.setUpdateOnlyWifi(false); 30 | BmobUpdateAgent.update(this); 31 | } 32 | 33 | @Override 34 | public void initData() { 35 | switchFragment(new SettingFragment()); 36 | //初始化并发起权限申请 37 | mPermissionHelper = new PermissionHelper(this, this); 38 | mPermissionHelper.requestPermissions(); 39 | } 40 | 41 | @Override 42 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 43 | if (mPermissionHelper.requestPermissionsResult(requestCode, permissions, grantResults)) { 44 | //权限请求结果,并已经处理了该回调 45 | return; 46 | } 47 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 48 | } 49 | 50 | @Override 51 | public int getPermissionsRequestCode() { 52 | return 19680; 53 | } 54 | 55 | @Override 56 | public String[] getPermissions() { 57 | return new String[]{ 58 | Manifest.permission.WRITE_EXTERNAL_STORAGE, 59 | Manifest.permission.READ_EXTERNAL_STORAGE, 60 | }; 61 | } 62 | 63 | @Override 64 | public void requestPermissionsSuccess() { 65 | 66 | } 67 | 68 | @Override 69 | public void requestPermissionsFail() { 70 | ToastUtils.toast(this, "应用需要权限才能正常运行!"); 71 | finish(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/activity/TabSettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.activity; 2 | 3 | import android.graphics.Color; 4 | import android.view.MenuItem; 5 | 6 | import com.lhy.xposed.mhzs.fragment.AdSettingFragment; 7 | import com.lhy.xposed.mhzs.fragment.TabSettingFragment; 8 | 9 | import androidx.appcompat.widget.Toolbar; 10 | 11 | public class TabSettingActivity extends BaseActivity { 12 | @Override 13 | protected void initToolbar(Toolbar mToolbar) { 14 | mToolbar.setTitle("底部栏设置"); 15 | mToolbar.setTitleTextColor(Color.WHITE); 16 | setSupportActionBar(mToolbar); 17 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 18 | } 19 | 20 | @Override 21 | protected void initView() { 22 | 23 | } 24 | 25 | @Override 26 | protected void initData() { 27 | switchFragment(new TabSettingFragment()); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/bean/DataBean.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * DataBean 7 | * 麻花影视 2.5.0之前 8 | */ 9 | @Deprecated 10 | public class DataBean { 11 | 12 | private String m3u8PlayUrl; 13 | 14 | @SerializedName(value = "m3u8Format") 15 | private M3u8FormatBean m3u8FormatBean; 16 | 17 | public void setM3u8PlayUrl(String m3u8PlayUrl) { 18 | this.m3u8PlayUrl = m3u8PlayUrl; 19 | } 20 | 21 | public String getM3u8PlayUrl() { 22 | return m3u8PlayUrl; 23 | } 24 | 25 | public void setM3u8Format(M3u8FormatBean m3u8Format) { 26 | this.m3u8FormatBean = m3u8Format; 27 | } 28 | 29 | public M3u8FormatBean getM3u8Format() { 30 | return m3u8FormatBean; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/bean/Feedback.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.bean; 2 | 3 | import cn.bmob.v3.BmobObject; 4 | 5 | public class Feedback extends BmobObject { 6 | private String detail; 7 | private String contact; 8 | private String device; 9 | private String framework; 10 | private String version; 11 | 12 | public String getDetail() { 13 | return detail; 14 | } 15 | 16 | public void setDetail(String detail) { 17 | this.detail = detail; 18 | } 19 | 20 | public String getContact() { 21 | return contact; 22 | } 23 | 24 | public void setContact(String contact) { 25 | this.contact = contact; 26 | } 27 | 28 | public String getDevice() { 29 | return device; 30 | } 31 | 32 | public void setDevice(String device) { 33 | this.device = device; 34 | } 35 | 36 | public String getFramework() { 37 | return framework; 38 | } 39 | 40 | public void setFramework(String framework) { 41 | this.framework = framework; 42 | } 43 | 44 | public String getVersion() { 45 | return version; 46 | } 47 | 48 | public void setVersion(String version) { 49 | this.version = version; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "Feedback{" + 55 | "detail='" + detail + '\'' + 56 | ", contact='" + contact + '\'' + 57 | ", device='" + device + '\'' + 58 | ", framework='" + framework + '\'' + 59 | ", version='" + version + '\'' + 60 | '}'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/bean/M3u8FormatBean.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.bean; 2 | 3 | 4 | import com.google.gson.annotations.SerializedName; 5 | 6 | /** 7 | * M3u8FormatBean 8 | * 麻花影视 2.5.0之前 9 | */ 10 | @Deprecated 11 | public class M3u8FormatBean { 12 | @SerializedName(value = "1080P") 13 | private String _$1080P; 14 | @SerializedName(value = "360P") 15 | private String _$360P; 16 | @SerializedName(value = "480P") 17 | private String _$480P; 18 | @SerializedName(value = "720P") 19 | private String _$720P; 20 | private String free; 21 | 22 | public String getM3u8Format(int i) { 23 | if (i == 0) { 24 | if (get_$360P() != null) { 25 | return get_$360P(); 26 | } 27 | return null; 28 | } else if (i == 1) { 29 | if (get_$480P() != null) { 30 | return get_$480P(); 31 | } 32 | return null; 33 | } else if (i == 2) { 34 | if (get_$720P() != null) { 35 | return get_$720P(); 36 | } 37 | return null; 38 | } else if (i == 3) { 39 | if (get_$1080P() != null) { 40 | return get_$1080P(); 41 | } 42 | return null; 43 | } else if (i != -1 || getFree() == null) { 44 | return null; 45 | } else { 46 | return getFree(); 47 | } 48 | } 49 | 50 | public String get_$720P() { 51 | return this._$720P; 52 | } 53 | 54 | public void set_$720P(String str) { 55 | this._$720P = str; 56 | } 57 | 58 | public String getFree() { 59 | return this.free; 60 | } 61 | 62 | public void setFree(String str) { 63 | this.free = str; 64 | } 65 | 66 | public String get_$480P() { 67 | return this._$480P; 68 | } 69 | 70 | public void set_$480P(String str) { 71 | this._$480P = str; 72 | } 73 | 74 | public String get_$360P() { 75 | return this._$360P; 76 | } 77 | 78 | public void set_$360P(String str) { 79 | this._$360P = str; 80 | } 81 | 82 | public String get_$1080P() { 83 | return this._$1080P; 84 | } 85 | 86 | public void set_$1080P(String str) { 87 | this._$1080P = str; 88 | } 89 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/bean/VideoInfoBean.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.bean; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | /** 6 | * VideoInfoBean 7 | * 麻花影视 2.5.0之前 8 | */ 9 | @Deprecated 10 | public class VideoInfoBean { 11 | private String code; 12 | @SerializedName(value = "data") 13 | private DataBean dataBean; 14 | private String description; 15 | private String imgAddr; 16 | private boolean success; 17 | private String videoAddr; 18 | 19 | public DataBean getDataBean() { 20 | return this.dataBean; 21 | } 22 | 23 | public void setDataBean(DataBean dataBean) { 24 | this.dataBean = dataBean; 25 | } 26 | 27 | public String getCode() { 28 | return this.code; 29 | } 30 | 31 | public void setCode(String str) { 32 | this.code = str; 33 | } 34 | 35 | public String getDescription() { 36 | return this.description; 37 | } 38 | 39 | public void setDescription(String str) { 40 | this.description = str; 41 | } 42 | 43 | public String getImgAddr() { 44 | return this.imgAddr; 45 | } 46 | 47 | public void setImgAddr(String str) { 48 | this.imgAddr = str; 49 | } 50 | 51 | public boolean isSuccess() { 52 | return this.success; 53 | } 54 | 55 | public void setSuccess(boolean z) { 56 | this.success = z; 57 | } 58 | 59 | public String getVideoAddr() { 60 | return this.videoAddr; 61 | } 62 | 63 | public void setVideoAddr(String str) { 64 | this.videoAddr = str; 65 | } 66 | 67 | public String toString() { 68 | StringBuilder stringBuilder = new StringBuilder(); 69 | stringBuilder.append("VideoInfo{dataBean="); 70 | stringBuilder.append(this.dataBean); 71 | stringBuilder.append(", code='"); 72 | stringBuilder.append(this.code); 73 | stringBuilder.append('\''); 74 | stringBuilder.append(", description='"); 75 | stringBuilder.append(this.description); 76 | stringBuilder.append('\''); 77 | stringBuilder.append(", imgAddr='"); 78 | stringBuilder.append(this.imgAddr); 79 | stringBuilder.append('\''); 80 | stringBuilder.append(", success="); 81 | stringBuilder.append(this.success); 82 | stringBuilder.append(", videoAddr='"); 83 | stringBuilder.append(this.videoAddr); 84 | stringBuilder.append('\''); 85 | stringBuilder.append('}'); 86 | return stringBuilder.toString(); 87 | } 88 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/fragment/AdSettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.fragment; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lhy.xposed.mhzs.R; 6 | 7 | import androidx.preference.Preference; 8 | import androidx.preference.PreferenceFragmentCompat; 9 | 10 | public class AdSettingFragment extends BasePreferenceFragment { 11 | @Override 12 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 13 | addPreferencesFromResource(R.xml.pref_mhzs_ad); 14 | setWorldReadable(); 15 | } 16 | 17 | @Override 18 | public boolean onPreferenceTreeClick(Preference preference) { 19 | return super.onPreferenceTreeClick(preference); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/fragment/BasePreferenceFragment.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.fragment; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.os.Bundle; 5 | 6 | import com.lhy.xposed.mhzs.helper.FileUtils; 7 | 8 | import java.io.File; 9 | 10 | import androidx.preference.PreferenceFragmentCompat; 11 | 12 | public class BasePreferenceFragment extends PreferenceFragmentCompat { 13 | @Override 14 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 15 | } 16 | 17 | /** 18 | * 设置Pref为可读 19 | */ 20 | @SuppressWarnings({"deprecation", "ResultOfMethodCallIgnored"}) 21 | @SuppressLint({"SetWorldReadable", "WorldReadableFiles"}) 22 | protected void setWorldReadable() { 23 | if (FileUtils.getDefaultPrefFile(getActivity()) 24 | .exists()) { 25 | for (File file : new File[]{FileUtils.getDataDir(getActivity()), FileUtils.getPrefDir(getActivity()), FileUtils.getDefaultPrefFile(getActivity())}) { 26 | file.setReadable(true, false); 27 | file.setExecutable(true, false); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/fragment/ExpSettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.fragment; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lhy.xposed.mhzs.R; 6 | 7 | import androidx.preference.Preference; 8 | 9 | /** 10 | * 实验性功能 11 | * 12 | * @author lhy 13 | * @time 2019年3月12日10:56:55 14 | */ 15 | public class ExpSettingFragment extends BasePreferenceFragment { 16 | @Override 17 | public void onCreatePreferences(Bundle bundle, String s) { 18 | addPreferencesFromResource(R.xml.pref_mhzs_exp); 19 | setWorldReadable(); 20 | } 21 | 22 | @Override 23 | public boolean onPreferenceTreeClick(Preference preference) { 24 | return super.onPreferenceTreeClick(preference); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/fragment/SettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.fragment; 2 | 3 | import android.content.ContentResolver; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.didikee.donate.AlipayDonate; 7 | import android.didikee.donate.WeiXinDonate; 8 | import android.graphics.BitmapFactory; 9 | import android.net.Uri; 10 | import android.os.Bundle; 11 | import android.os.Environment; 12 | import android.util.Log; 13 | 14 | import androidx.preference.Preference; 15 | import androidx.preference.PreferenceFragmentCompat; 16 | import androidx.preference.PreferenceGroup; 17 | import androidx.preference.SwitchPreferenceCompat; 18 | 19 | import com.lhy.xposed.mhzs.R; 20 | import com.lhy.xposed.mhzs.activity.AboutActivity; 21 | import com.lhy.xposed.mhzs.activity.AdSettingActivity; 22 | import com.lhy.xposed.mhzs.activity.ExpSettingActivity; 23 | import com.lhy.xposed.mhzs.activity.FeedbackActivity; 24 | import com.lhy.xposed.mhzs.activity.HelpActivity; 25 | import com.lhy.xposed.mhzs.activity.TabSettingActivity; 26 | import com.lhy.xposed.mhzs.helper.ToastUtils; 27 | 28 | import java.io.File; 29 | import java.io.InputStream; 30 | 31 | public class SettingFragment extends BasePreferenceFragment { 32 | private PreferenceGroup pcDetailPreferenceGroup; 33 | private SwitchPreferenceCompat switchPreferenceCompat; 34 | 35 | @Override 36 | public void onCreatePreferences(Bundle bundle, String s) { 37 | addPreferencesFromResource(R.xml.pref_mhzs); 38 | setWorldReadable(); 39 | switchPreferenceCompat = findPreference("global_set"); 40 | pcDetailPreferenceGroup = findPreference("pc_detail"); 41 | 42 | SharedPreferences sp = getPreferenceManager().getSharedPreferences(); 43 | pcDetailPreferenceGroup.setVisible(sp.getBoolean("global_set", false)); 44 | 45 | 46 | // TODO: 2019/3/14 0014 检查模块运行状态1/3 47 | // if (!isModuleActive() && !isExpModuleActive()) { 48 | // pcDetailPreferenceGroup.setVisible(false); 49 | // switchPreferenceCompat.setChecked(false); 50 | // } 51 | } 52 | 53 | @Override 54 | public boolean onPreferenceTreeClick(Preference preference) { 55 | switch (preference.getKey()) { 56 | case "global_set": 57 | globalSet(preference); 58 | return true; 59 | case "ad_set": 60 | startActivity(new Intent(getActivity(), AdSettingActivity.class)); 61 | return true; 62 | case "tab_set": 63 | startActivity(new Intent(getActivity(), TabSettingActivity.class)); 64 | return true; 65 | case "help": 66 | startActivity(new Intent(getActivity(), HelpActivity.class)); 67 | return true; 68 | case "github": 69 | startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/1595901624/mhzs"))); 70 | return true; 71 | case "donate_alipay": 72 | donateAlipay(); 73 | return true; 74 | case "lucky_alipay": 75 | getAlipayLucky(); 76 | return true; 77 | case "donate_wx": 78 | donateWeixin(); 79 | return true; 80 | case "exp_set": 81 | startActivity(new Intent(getActivity(), ExpSettingActivity.class)); 82 | return true; 83 | case "feedback": 84 | startActivity(new Intent(getActivity(), FeedbackActivity.class)); 85 | return true; 86 | case "about": 87 | startActivity(new Intent(getActivity(), AboutActivity.class)); 88 | return true; 89 | default: 90 | break; 91 | } 92 | return false; 93 | } 94 | 95 | /** 96 | * 领红包 97 | */ 98 | @Deprecated 99 | private void getAlipayLucky() { 100 | String luckyCode = "c1x08425objyhrkgjby6f26"; 101 | boolean hasInstalledAlipayClient = AlipayDonate.hasInstalledAlipayClient(getActivity()); 102 | if (hasInstalledAlipayClient) { 103 | AlipayDonate.startAlipayClient(getActivity(), luckyCode); 104 | } else { 105 | ToastUtils.toast(getActivity(), "当前设备未安装支付宝!"); 106 | } 107 | } 108 | 109 | 110 | private void globalSet(Preference preference) { 111 | // TODO: 2019/3/14 0014 检查模块运行状态2/3 112 | // if (switchPreferenceCompat.isChecked() && !isModuleActive() && !isExpModuleActive()) { 113 | // switchPreferenceCompat.setChecked(false); 114 | // pcDetailPreferenceGroup.setVisible(false); 115 | // ToastUtils.toast(getActivity(), "请在Xposed框架中激活!"); 116 | // return; 117 | // } 118 | 119 | if (switchPreferenceCompat.isChecked()) { 120 | pcDetailPreferenceGroup.setVisible(true); 121 | ToastUtils.toast(getActivity(), "麻花助手已经开启!"); 122 | } else { 123 | pcDetailPreferenceGroup.setVisible(false); 124 | ToastUtils.toast(getActivity(), "麻花助手已经关闭!"); 125 | } 126 | 127 | } 128 | 129 | /** 130 | * 支付宝捐献 131 | */ 132 | private void donateAlipay() { 133 | String payCode = "fkx09681rnsrxn9nog4sy2c"; 134 | boolean hasInstalledAlipayClient = AlipayDonate.hasInstalledAlipayClient(getActivity()); 135 | if (hasInstalledAlipayClient) { 136 | AlipayDonate.startAlipayClient(getActivity(), payCode); 137 | } else { 138 | ToastUtils.toast(getActivity(), "当前设备未安装支付宝!"); 139 | } 140 | } 141 | 142 | /** 143 | * 微信捐献 144 | */ 145 | private void donateWeixin() { 146 | InputStream weixinQrIs = getResources().openRawResource(R.raw.wechatc); 147 | String qrPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AndroidDonateSample" + File.separator + 148 | "wechatc.jpg"; 149 | WeiXinDonate.saveDonateQrImage2SDCard(qrPath, BitmapFactory.decodeStream(weixinQrIs)); 150 | WeiXinDonate.donateViaWeiXin(getActivity(), qrPath); 151 | } 152 | 153 | /********************************************************************************************** 154 | * 155 | * 以下方法勿动 156 | * 157 | **********************************************************************************************/ 158 | 159 | 160 | public boolean isModuleActive() { 161 | // Tai-Chi 在某些机型上hook短方法有问题,这里认为添加日志增大方法长度确保能hook成功。 162 | Log.i("fake", "isModuleActive"); 163 | return false; 164 | } 165 | 166 | public boolean isExpModuleActive() { 167 | boolean isActive = false; 168 | try { 169 | ContentResolver contentResolver = getActivity().getContentResolver(); 170 | Uri uri = Uri.parse("content://me.weishu.exposed.CP/"); 171 | Bundle result = contentResolver.call(uri, "active", null, null); 172 | if (result == null) { 173 | return false; 174 | } 175 | isActive = result.getBoolean("active", false); 176 | } catch (Exception e) { 177 | e.printStackTrace(); 178 | } 179 | return isActive; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/fragment/TabSettingFragment.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.fragment; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.lhy.xposed.mhzs.R; 6 | import com.lhy.xposed.mhzs.activity.BaseActivity; 7 | 8 | import androidx.preference.PreferenceFragmentCompat; 9 | 10 | public class TabSettingFragment extends BasePreferenceFragment { 11 | @Override 12 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 13 | addPreferencesFromResource(R.xml.pref_mhzs_tab); 14 | setWorldReadable(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/Config.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * 配置文件 8 | */ 9 | public interface Config { 10 | String HELP_MARKDOWN_URL = "https://raw.githubusercontent.com/1595901624/mhzs/master/README.md"; 11 | Set HOOK_APPLICATION_PACKAGE_NAME = new HashSet() {{ 12 | // add("com.lhy.xposed.mhzs"); 13 | add("com.amahua.ywofnbfd"); 14 | add("com.amahua.ompimdrt"); 15 | add("com.amahua.vwzasawq"); 16 | }}; 17 | /*麻花影视支持版本*/ 18 | String SUPPORT_MHYS_VERISON = "2.7.0"; 19 | // String HOOK_APPLICATION_PRE_PACKAGE_NAME = "com.amahua"; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/Constant.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | public class Constant { 4 | 5 | 6 | public static String CURRENT_HOOK_PACKAGE_NAME = ""; 7 | public static final String $id = "com.mh.movie.core.R$id"; 8 | public static final String $MHApplication = "com.mh.movie.core.mvp.ui.MHApplication"; 9 | 10 | /** 11 | * 麻花影视的activity名 12 | */ 13 | public static class act { 14 | public static final String $MainActivity = "com.mh.movie.core.mvp.ui.activity.main.MainActivity"; 15 | public static final String $SplashActivity = "com.mh.movie.core.mvp.ui.activity.SplashActivity"; 16 | public static final String $PlayerActivity = "com.mh.movie.core.mvp.ui.activity.player.PlayerActivity"; 17 | public static final String $ScreeningActivity = "com.mh.movie.core.mvp.ui.activity.player.ScreeningActivity"; 18 | 19 | public static final String $WXEntryActivity = CURRENT_HOOK_PACKAGE_NAME + ".wxapi.WXEntryActivity"; 20 | } 21 | 22 | public static class fgmt { 23 | public static final String $TaskFragment = "com.mh.movie.core.mvp.ui.fragment.TaskFragment"; 24 | public static final String $MyFragment = "com.mh.movie.core.mvp.ui.fragment.MyFragment"; 25 | } 26 | 27 | public static class prst { 28 | public static final String $PlayerPresenter = "com.mh.movie.core.mvp.presenter.player.PlayerPresenter"; 29 | public static final String $MyPresenter = "com.mh.movie.core.mvp.presenter.MyPresenter"; 30 | } 31 | 32 | public static class util { 33 | public static final String $MyTimeTaskHandler = "com.mh.movie.core.mvp.ui.utils.MyTimeTaskHandler"; 34 | } 35 | 36 | public static class db { 37 | public static final String $TableCommodity = "com.mh.movie.core.mvp.model.db.TableCommodity"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import android.content.Context; 4 | import android.os.Environment; 5 | 6 | import com.lhy.xposed.mhzs.BuildConfig; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | 13 | 14 | /** 15 | * Created by zpp0196 on 2019/2/9. 16 | */ 17 | 18 | public class FileUtils { 19 | private static final String FILE_PREF_NAME = BuildConfig.APPLICATION_ID + "_preferences.xml"; 20 | 21 | public static boolean copyFile(File srcFile, File targetFile) { 22 | FileInputStream ins = null; 23 | FileOutputStream out = null; 24 | try { 25 | if (targetFile.exists()) { 26 | targetFile.delete(); 27 | } 28 | File targetParent = targetFile.getParentFile(); 29 | if (!targetParent.exists()) { 30 | targetParent.mkdirs(); 31 | } 32 | targetFile.createNewFile(); 33 | ins = new FileInputStream(srcFile); 34 | out = new FileOutputStream(targetFile); 35 | byte[] b = new byte[1024]; 36 | int n; 37 | while ((n = ins.read(b)) != -1) { 38 | out.write(b, 0, n); 39 | } 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | return false; 43 | } finally { 44 | try { 45 | if (ins != null) { 46 | ins.close(); 47 | } 48 | if (out != null) { 49 | out.close(); 50 | } 51 | } catch (IOException e) { 52 | e.printStackTrace(); 53 | } 54 | } 55 | return true; 56 | } 57 | 58 | public static File getDataDir(Context context) { 59 | return new File(context.getApplicationInfo().dataDir); 60 | } 61 | 62 | public static File getPrefDir(Context context) { 63 | return new File(getDataDir(context), "shared_prefs"); 64 | } 65 | 66 | public static File getDefaultPrefFile(Context context) { 67 | return new File(getPrefDir(context), FILE_PREF_NAME); 68 | } 69 | 70 | public static File getBackupPrefsFile() { 71 | return new File(getBackupDir(), FILE_PREF_NAME); 72 | } 73 | 74 | private static File getBackupDir() { 75 | return new File(Environment.getExternalStorageDirectory(), "QQPurify"); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/HYHelper.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | 8 | import de.robv.android.xposed.XposedHelpers; 9 | 10 | 11 | public class HYHelper { 12 | 13 | /** 14 | * 获取packageCode 15 | * 16 | * @param context 17 | * @return 18 | */ 19 | public static long getPackageCode(Context context) { 20 | PackageManager manager = context.getPackageManager(); 21 | long code = 0; 22 | try { 23 | PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); 24 | code = info.getLongVersionCode(); 25 | } catch (PackageManager.NameNotFoundException e) { 26 | e.printStackTrace(); 27 | } 28 | return code; 29 | } 30 | 31 | 32 | /** 33 | * 获取packageName 34 | * 35 | * @param context 36 | * @return 37 | */ 38 | public static String getVerisonName(Context context) { 39 | PackageManager manager = context.getPackageManager(); 40 | String name = null; 41 | try { 42 | PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0); 43 | name = info.versionName; 44 | } catch (PackageManager.NameNotFoundException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | return name; 49 | } 50 | 51 | /*** 52 | * 53 | */ 54 | public static int getViewId(ClassLoader classLoader, String idName) throws ClassNotFoundException { 55 | return XposedHelpers.getStaticIntField(classLoader.loadClass(Constant.$id), "rl_main_partner"); 56 | } 57 | 58 | /** 59 | * 获取设备信息 60 | * 61 | * @return 62 | */ 63 | public static String getDeviceInfo() { 64 | return "设备品牌:" + Build.BRAND + " " + Build.MODEL + ", 安卓版本:" 65 | + Build.VERSION.RELEASE + "(" + Build.VERSION.SDK_INT + ")"; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import android.util.Log; 4 | 5 | import com.lhy.xposed.mhzs.BuildConfig; 6 | 7 | public class LogUtil { 8 | private final static String TAG = "XP_MHYSZY"; 9 | 10 | private LogUtil() { 11 | } 12 | 13 | public static void e(String msg) { 14 | if (BuildConfig.DEBUG) { 15 | Log.e(TAG, msg); 16 | } 17 | } 18 | 19 | public static void w(String msg) { 20 | if (BuildConfig.DEBUG) { 21 | Log.w(TAG, msg); 22 | } 23 | } 24 | 25 | public static void i(String msg) { 26 | if (BuildConfig.DEBUG) { 27 | Log.i(TAG, msg); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.widget.Toast; 6 | 7 | public class ToastUtils { 8 | 9 | private ToastUtils() { 10 | 11 | } 12 | 13 | public static void toast(Activity activity, String msg) { 14 | Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show(); 15 | } 16 | 17 | public static void toast(Activity activity, int resId) { 18 | Toast.makeText(activity, resId, Toast.LENGTH_SHORT).show(); 19 | } 20 | 21 | public static void toastLong(Activity activity, String msg) { 22 | Toast.makeText(activity, msg, Toast.LENGTH_LONG).show(); 23 | } 24 | 25 | public static void toastLong(Activity activity, int resId) { 26 | Toast.makeText(activity, resId, Toast.LENGTH_LONG).show(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/helper/XPrefUtils.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.helper; 2 | 3 | import com.lhy.xposed.mhzs.BuildConfig; 4 | 5 | import java.lang.ref.WeakReference; 6 | import java.util.ArrayList; 7 | import java.util.HashSet; 8 | import java.util.List; 9 | import java.util.Set; 10 | 11 | import de.robv.android.xposed.XSharedPreferences; 12 | 13 | /** 14 | * Created by zpp0196 on 2018/4/11. 15 | */ 16 | 17 | public class XPrefUtils { 18 | 19 | private static WeakReference xSharedPreferences = new WeakReference<>(null); 20 | 21 | public static XSharedPreferences getPref() { 22 | XSharedPreferences preferences = xSharedPreferences.get(); 23 | if (preferences == null) { 24 | preferences = new XSharedPreferences(BuildConfig.APPLICATION_ID); 25 | preferences.makeWorldReadable(); 26 | preferences.reload(); 27 | xSharedPreferences = new WeakReference<>(preferences); 28 | } else { 29 | preferences.reload(); 30 | } 31 | return preferences; 32 | } 33 | 34 | // private static Set getStringSet(String key) { 35 | // return getPref().getStringSet(key, new HashSet<>()); 36 | // } 37 | // 38 | // public static List getStringList(String key) { 39 | // Set set = getStringSet(key); 40 | // List list = new ArrayList<>(); 41 | // list.addAll(set); 42 | // return list; 43 | // } 44 | // 45 | // public static List getIntegerList(String key) { 46 | // List stringList = getStringList(key); 47 | // List integerList = new ArrayList<>(); 48 | // for (String str : stringList) { 49 | // integerList.add(Integer.valueOf(str)); 50 | // } 51 | // return integerList; 52 | // } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/permission/PermissionHelper.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.permission; 2 | 3 | import android.app.Activity; 4 | import android.content.pm.PackageManager; 5 | 6 | import androidx.annotation.NonNull; 7 | 8 | /** 9 | * 动态权限帮助类 10 | */ 11 | public class PermissionHelper { 12 | 13 | private Activity mActivity; 14 | private PermissionInterface mPermissionInterface; 15 | 16 | public PermissionHelper(@NonNull Activity activity, @NonNull PermissionInterface permissionInterface) { 17 | mActivity = activity; 18 | mPermissionInterface = permissionInterface; 19 | } 20 | 21 | /** 22 | * 开始请求权限。 23 | * 方法内部已经对Android M 或以上版本进行了判断,外部使用不再需要重复判断。 24 | * 如果设备还不是M或以上版本,则也会回调到requestPermissionsSuccess方法。 25 | */ 26 | public void requestPermissions(){ 27 | String[] deniedPermissions = PermissionUtil.getDeniedPermissions(mActivity, mPermissionInterface.getPermissions()); 28 | if(deniedPermissions != null && deniedPermissions.length > 0){ 29 | PermissionUtil.requestPermissions(mActivity, deniedPermissions, mPermissionInterface.getPermissionsRequestCode()); 30 | }else{ 31 | mPermissionInterface.requestPermissionsSuccess(); 32 | } 33 | } 34 | 35 | /** 36 | * 在Activity中的onRequestPermissionsResult中调用 37 | * @param requestCode 38 | * @param permissions 39 | * @param grantResults 40 | * @return true 代表对该requestCode感兴趣,并已经处理掉了。false 对该requestCode不感兴趣,不处理。 41 | */ 42 | public boolean requestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults){ 43 | if(requestCode == mPermissionInterface.getPermissionsRequestCode()){ 44 | boolean isAllGranted = true;//是否全部权限已授权 45 | for(int result : grantResults){ 46 | if(result == PackageManager.PERMISSION_DENIED){ 47 | isAllGranted = false; 48 | break; 49 | } 50 | } 51 | if(isAllGranted){ 52 | //已全部授权 53 | mPermissionInterface.requestPermissionsSuccess(); 54 | }else{ 55 | //权限有缺失 56 | mPermissionInterface.requestPermissionsFail(); 57 | } 58 | return true; 59 | } 60 | return false; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/permission/PermissionInterface.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.permission; 2 | 3 | /** 4 | * 权限请求接口 5 | */ 6 | public interface PermissionInterface { 7 | 8 | /** 9 | * 可设置请求权限请求码 10 | */ 11 | int getPermissionsRequestCode(); 12 | 13 | /** 14 | * 设置需要请求的权限 15 | */ 16 | String[] getPermissions(); 17 | 18 | /** 19 | * 请求权限成功回调 20 | */ 21 | void requestPermissionsSuccess(); 22 | 23 | /** 24 | * 请求权限失败回调 25 | */ 26 | void requestPermissionsFail(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/permission/PermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.permission; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.os.Build; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * 动态权限工具类 12 | */ 13 | public class PermissionUtil { 14 | 15 | /** 16 | * 判断是否有某个权限 17 | * 18 | * @param context 19 | * @param permission 20 | * @return 21 | */ 22 | public static boolean hasPermission(Context context, String permission) { 23 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 24 | if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 25 | return false; 26 | } 27 | } 28 | return true; 29 | } 30 | 31 | /** 32 | * 弹出对话框请求权限 33 | * 34 | * @param activity 35 | * @param permissions 36 | * @param requestCode 37 | */ 38 | public static void requestPermissions(Activity activity, String[] permissions, int requestCode) { 39 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 40 | activity.requestPermissions(permissions, requestCode); 41 | } 42 | } 43 | 44 | /** 45 | * 返回缺失的权限 46 | * 47 | * @param context 48 | * @param permissions 49 | * @return 返回缺少的权限,null 意味着没有缺少权限 50 | */ 51 | public static String[] getDeniedPermissions(Context context, String[] permissions) { 52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 53 | ArrayList deniedPermissionList = new ArrayList<>(); 54 | for (String permission : permissions) { 55 | if (context.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) { 56 | deniedPermissionList.add(permission); 57 | } 58 | } 59 | int size = deniedPermissionList.size(); 60 | if (size > 0) { 61 | return deniedPermissionList.toArray(new String[deniedPermissionList.size()]); 62 | } 63 | } 64 | return null; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/AutoSignPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.content.SharedPreferences; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | 9 | import com.lhy.xposed.mhzs.helper.Constant; 10 | import com.lhy.xposed.mhzs.helper.LogUtil; 11 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 12 | 13 | import java.lang.reflect.Field; 14 | 15 | import de.robv.android.xposed.XC_MethodHook; 16 | import de.robv.android.xposed.XposedHelpers; 17 | 18 | /** 19 | * 自动签到插件 20 | * 21 | * @author lhy 22 | * @time 2019年3月14日14:26:17 23 | *

24 | * 该插件实现半自动签到,只有用户登录后且当点击到“任务”页面时,才会触发签到,否则不会签到。 25 | *

26 | *

27 | * * @version 1.1 2019年3月15日15:33:18 28 | * * 修改Application的获取方式 29 | */ 30 | public class AutoSignPlugin implements IPlugin { 31 | private final String $TaskWidget = "com.mh.movie.core.mvp.ui.widget.TaskWidget"; 32 | private final String $TaskViewHolder = "com.mh.movie.core.mvp.ui.holder.ad"; 33 | private final String $UserTaskResponse$ListBean = "com.mh.movie.core.mvp.model.entity.response.UserTaskResponse$ListBean"; 34 | 35 | @Override 36 | public void run(final ClassLoader classLoader) throws Throwable { 37 | 38 | final Class $TaskViewHolderClass = classLoader.loadClass($TaskViewHolder); 39 | final Class $UserTaskResponse$ListBeanClass = classLoader.loadClass($UserTaskResponse$ListBean); 40 | 41 | XposedHelpers.findAndHookMethod(Constant.fgmt.$TaskFragment + "$3", classLoader, "a", 42 | $TaskViewHolderClass, $UserTaskResponse$ListBeanClass, int.class, new XC_MethodHook() { 43 | @Override 44 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 45 | super.beforeHookedMethod(param); 46 | } 47 | 48 | @Override 49 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 50 | super.afterHookedMethod(param); 51 | 52 | Field taskActionTextViewField = XposedHelpers.findField($TaskViewHolderClass, "e"); 53 | taskActionTextViewField.setAccessible(true); 54 | TextView taskActionTextView = (TextView) taskActionTextViewField.get(param.args[0]); 55 | 56 | if (taskActionTextView.getText().toString().equals("点击签到")) { 57 | //获取Application 58 | Field f = XposedHelpers.findField($TaskViewHolderClass, "itemView"); 59 | f.setAccessible(true); 60 | View view = (View) f.get(param.args[0]); 61 | Application application = (Application) view.getContext().getApplicationContext(); 62 | SharedPreferences sp = application.getSharedPreferences("config", Context.MODE_PRIVATE); 63 | boolean isLogin = sp.getBoolean("key_islogin", false); 64 | LogUtil.e("isLogin = " + isLogin); 65 | 66 | if (!isLogin) 67 | return; 68 | taskActionTextView.performClick(); 69 | } 70 | } 71 | }); 72 | 73 | } 74 | 75 | @Override 76 | public boolean isOpen() { 77 | return XPrefUtils.getPref().getBoolean("auto_sign", false); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearBootAdPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.content.Context; 4 | 5 | import com.lhy.xposed.mhzs.helper.LogUtil; 6 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 7 | 8 | import de.robv.android.xposed.XC_MethodHook; 9 | import de.robv.android.xposed.XposedHelpers; 10 | 11 | /** 12 | * 清理启动页的广告,5s启动 13 | * 14 | * @author lhy 15 | * @time 2019年2月16日13:12:33 16 | */ 17 | public class ClearBootAdPlugin implements IPlugin { 18 | 19 | private final String dataHelperClassName = "com.jess.arms.c.d"; 20 | private final String constantsClassName = "com.mh.movie.core.mvp.ui.b"; 21 | private final String loginResponseClassName = "com.mh.movie.core.mvp.model.entity.response.LoginResponse"; 22 | 23 | @Override 24 | public void run(final ClassLoader classLoader) throws Throwable { 25 | /** 26 | * 禁止加载广告历史记录 27 | * 28 | * 【方法1】 29 | * 此变量名版本更新可能会改变 30 | */ 31 | // XposedHelpers.setStaticObjectField(classLoader.loadClass(constantsClassName), "w", "splash_no_ad_list"); 32 | 33 | /** 34 | * 【方法2】 35 | * 此变量名版本更新可能会改变,但改变的几率很小 36 | */ 37 | XposedHelpers.findAndHookMethod(dataHelperClassName, classLoader, "a", Context.class, String.class, 38 | new XC_MethodHook() { 39 | @Override 40 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 41 | super.beforeHookedMethod(param); 42 | if ((param.args[1] + "").equals("splash_ad_list")) { 43 | param.args[1] = "splash_no_ad_list"; 44 | LogUtil.e(param.args[1] + "---"); 45 | } 46 | } 47 | }); 48 | /** 49 | * 将AdList设置为空 50 | * 清除5s启动已经包含此功能 51 | */ 52 | // TODO: 2019/2/22 0022 Exposed/VXP ISSUE--TOO SHORT METHOD!!! 53 | // XposedHelpers.findAndHookMethod(loginResponseClassName, classLoader, "getAdsList", new XC_MethodHook() { 54 | // @Override 55 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 56 | // super.afterHookedMethod(param); 57 | // LogUtil.e("hook getAdsList null!"); 58 | // param.setResult(null); 59 | // } 60 | // }); 61 | 62 | } 63 | 64 | @Override 65 | public boolean isOpen() { 66 | return XPrefUtils.getPref().getBoolean("ad_boot", true); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearDanmuPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.LinearLayout; 7 | 8 | import com.lhy.xposed.mhzs.helper.Constant; 9 | import com.lhy.xposed.mhzs.helper.LogUtil; 10 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 11 | 12 | import java.lang.reflect.Field; 13 | 14 | import de.robv.android.xposed.XC_MethodHook; 15 | import de.robv.android.xposed.XposedHelpers; 16 | 17 | /** 18 | * 去除弹幕 19 | *

20 | * 该功能开启后,内置弹幕设置开关将失效 21 | * 22 | * @time 2019年4月12日09:56:37 23 | * @auth lhy 24 | */ 25 | public class ClearDanmuPlugin implements IPlugin { 26 | private String $DanmakuVideoPlayer = "com.mh.movie.core.mvp.ui.activity.player.DanmakuVideoPlayer"; 27 | 28 | @Override 29 | public void run(final ClassLoader classLoader) throws Throwable { 30 | XposedHelpers.findAndHookMethod($DanmakuVideoPlayer, classLoader, "g", new XC_MethodHook() { 31 | @Override 32 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 33 | super.afterHookedMethod(param); 34 | LogUtil.e("clear danmuku ----"); 35 | int llDanmakuViewId = XposedHelpers.getStaticIntField(classLoader.loadClass(Constant.$id), "ll_danmaku_view"); 36 | View view = (View) param.thisObject; 37 | LinearLayout llDanmakuView = view.findViewById(llDanmakuViewId); 38 | llDanmakuView.setVisibility(View.GONE); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public boolean isOpen() { 45 | return XPrefUtils.getPref().getBoolean("clear_danmu", false); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearFiveSecondsPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.app.Activity; 4 | import android.content.Intent; 5 | 6 | import com.lhy.xposed.mhzs.helper.Constant; 7 | import com.lhy.xposed.mhzs.helper.HYHelper; 8 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 9 | 10 | import java.util.List; 11 | 12 | import de.robv.android.xposed.XC_MethodReplacement; 13 | import de.robv.android.xposed.XposedHelpers; 14 | 15 | /** 16 | * 去除5s倒计时 17 | * 18 | * @time 2019年3月6日19:16:12 19 | */ 20 | public class ClearFiveSecondsPlugin implements IPlugin { 21 | 22 | @Override 23 | public void run(final ClassLoader classLoader) throws Throwable { 24 | /** 25 | * 在com.mh.movie.core.mvp.ui.activity.SplashActivity中 26 | * 替换a()方法,去除5s启动 27 | * 28 | * 此变量名版本更新可能会改变 29 | */ 30 | XposedHelpers.findAndHookMethod(Constant.act.$SplashActivity, classLoader, "a", long.class, List.class, boolean.class, new XC_MethodReplacement() { 31 | @Override 32 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 33 | //跳转MainActivity,并结束当前进程 34 | Class clazz = classLoader.loadClass(Constant.act.$MainActivity); 35 | Activity activity = (Activity) methodHookParam.thisObject; 36 | 37 | Intent intent = new Intent(activity, clazz); 38 | XposedHelpers.callMethod(activity, "startActivity", intent); 39 | XposedHelpers.callMethod(activity, "finish"); 40 | return null; 41 | } 42 | }); 43 | } 44 | 45 | @Override 46 | public boolean isOpen() { 47 | return XPrefUtils.getPref().getBoolean("five_seconds", true); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearMainAdPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.LogUtil; 4 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 5 | 6 | import java.util.List; 7 | 8 | import de.robv.android.xposed.XC_MethodReplacement; 9 | import de.robv.android.xposed.XposedHelpers; 10 | 11 | /** 12 | * 清理主界面广告 13 | * 包括:“推荐”,“电影”,“电视剧” 14 | * 15 | * 该插件全版本通用 16 | * 17 | * @author lhy 18 | * @time 2019年2月16日14:12:33 19 | */ 20 | public class ClearMainAdPlugin implements IPlugin { 21 | private final String movieCardViewClassName = "com.mh.movie.core.mvp.ui.widget.MovieCardView"; 22 | 23 | @Override 24 | public void run(ClassLoader classLoader) throws Throwable { 25 | 26 | /** 27 | * 在com.mh.movie.core.mvp.ui.widget.MovieCardView中 28 | * 替换setShowBanner方法,去掉广告 29 | */ 30 | // TODO: 2019/3/6 0006 VXP/EXP TOO SHORT METHOD 31 | // XposedHelpers.findAndHookMethod(movieCardViewClassName, classLoader, "setShowBanner", List.class, new XC_MethodReplacement() { 32 | // @Override 33 | // protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 34 | // LogUtil.e("hook setShowBanner method!"); 35 | // return null; 36 | // } 37 | // }); 38 | 39 | XposedHelpers.findAndHookMethod(movieCardViewClassName, classLoader, "c", new XC_MethodReplacement() { 40 | @Override 41 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 42 | LogUtil.e("hook setShowBanner2 method!"); 43 | return null; 44 | } 45 | }); 46 | 47 | } 48 | 49 | @Override 50 | public boolean isOpen() { 51 | return XPrefUtils.getPref().getBoolean("ad_main", true); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearMarqueePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.os.Bundle; 4 | import android.os.Message; 5 | 6 | import com.lhy.xposed.mhzs.helper.Constant; 7 | import com.lhy.xposed.mhzs.helper.LogUtil; 8 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 9 | 10 | import de.robv.android.xposed.XC_MethodHook; 11 | import de.robv.android.xposed.XposedHelpers; 12 | 13 | /** 14 | * 清除底部滚动广告 15 | * 16 | * @author lhy 17 | * @time 2019年3月7日13:37:05 18 | */ 19 | // TODO: 2019/3/15 0015 BUG 20 | public class ClearMarqueePlugin implements IPlugin { 21 | 22 | @Override 23 | public void run(ClassLoader classLoader) throws Throwable { 24 | XposedHelpers.findAndHookMethod(Constant.util.$MyTimeTaskHandler, classLoader, "handleMessage", Message.class, new XC_MethodHook() { 25 | @Override 26 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 27 | super.beforeHookedMethod(param); 28 | Message msg = (Message) param.args[0]; 29 | // LogUtil.e("msg.what = " + msg.what); 30 | if (msg.what == 9999) { 31 | msg.what = 5211314; 32 | // LogUtil.e("ClearMarqueePlugin run"); 33 | } 34 | } 35 | 36 | @Override 37 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 38 | super.afterHookedMethod(param); 39 | } 40 | }); 41 | } 42 | 43 | @Override 44 | public boolean isOpen() { 45 | return XPrefUtils.getPref().getBoolean("ad_marquee", false); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearMyFragmentAdPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.Constant; 4 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 5 | 6 | import de.robv.android.xposed.XC_MethodReplacement; 7 | import de.robv.android.xposed.XposedHelpers; 8 | 9 | /** 10 | * 清除MyFragment中的广告 11 | *

12 | * 不会请求广告数据,从而消耗多余流量 13 | * 14 | * @author lhy 15 | * @time 2019年4月8日17:25:21 16 | */ 17 | public class ClearMyFragmentAdPlugin implements IPlugin { 18 | @Override 19 | public void run(ClassLoader classLoader) throws Throwable { 20 | XposedHelpers.findAndHookMethod(Constant.prst.$MyPresenter, classLoader, "e", XC_MethodReplacement.DO_NOTHING); 21 | } 22 | 23 | @Override 24 | public boolean isOpen() { 25 | return XPrefUtils.getPref().getBoolean("ad_my", true); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/ClearPlayerAdPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.Constant; 4 | import com.lhy.xposed.mhzs.helper.LogUtil; 5 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 6 | 7 | import de.robv.android.xposed.XC_MethodReplacement; 8 | import de.robv.android.xposed.XposedBridge; 9 | import de.robv.android.xposed.XposedHelpers; 10 | 11 | /** 12 | * 清理播放界面广告 13 | * 包括:“推荐”,“电影”,“电视剧” 14 | * 15 | * @author lhy 16 | * @time 2019年2月16日15:12:33 17 | */ 18 | public class ClearPlayerAdPlugin implements IPlugin { 19 | 20 | @Override 21 | public void run(ClassLoader classLoader) throws Throwable { 22 | /** 23 | * 在com.mh.movie.core.mvp.presenter.player.PlayerPresenter中 24 | * 替换g()方法,去除播放页面的广告 -BootadsListBean- 25 | * 26 | * 此变量名版本更新可能会改变 27 | */ 28 | XposedHelpers.findAndHookMethod(Constant.prst.$PlayerPresenter, classLoader, "g", int.class, new XC_MethodReplacement() { 29 | @Override 30 | protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 31 | LogUtil.e("hook g method!"); 32 | return null; 33 | } 34 | }); 35 | } 36 | 37 | @Override 38 | public boolean isOpen() { 39 | return XPrefUtils.getPref().getBoolean("ad_player", true); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/CustomMainInterfacePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.RelativeLayout; 7 | 8 | import com.lhy.xposed.mhzs.helper.Constant; 9 | import com.lhy.xposed.mhzs.helper.LogUtil; 10 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 11 | 12 | import de.robv.android.xposed.XC_MethodHook; 13 | import de.robv.android.xposed.XposedHelpers; 14 | 15 | /** 16 | * 自定义主界面的底部按钮 17 | * 该插件全版本通用 18 | * 19 | * @author lhy 20 | * @time 2019年2月18日11:51:33 21 | */ 22 | public class CustomMainInterfacePlugin implements IPlugin { 23 | 24 | @Override 25 | public void run(final ClassLoader classLoader) throws Throwable { 26 | 27 | XposedHelpers.findAndHookMethod(Constant.act.$MainActivity, classLoader, "c", Bundle.class, new XC_MethodHook() { 28 | @Override 29 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 30 | LogUtil.e("hook c method!"); 31 | super.beforeHookedMethod(param); 32 | Class R$idClass = classLoader.loadClass(Constant.$id); 33 | Activity mMainActivity = (Activity) param.thisObject; 34 | 35 | if (XPrefUtils.getPref().getBoolean("tab2", false)) { 36 | //第二个按钮 37 | try { 38 | int rlMainTVId = XposedHelpers.getStaticIntField(R$idClass, "rl_main_tv"); 39 | RelativeLayout relativeLayout = mMainActivity.findViewById(rlMainTVId); 40 | relativeLayout.setVisibility(View.GONE); 41 | } catch (Exception e) { 42 | LogUtil.e("R.id.rl_main_tv Unknown Error!"); 43 | } 44 | } 45 | 46 | if (XPrefUtils.getPref().getBoolean("tab3", true)) { 47 | //第三个按钮 48 | try { 49 | int rlMainPartnerId = XposedHelpers.getStaticIntField(R$idClass, "rl_main_partner"); 50 | RelativeLayout relativeLayout = mMainActivity.findViewById(rlMainPartnerId); 51 | relativeLayout.setVisibility(View.GONE); 52 | } catch (Exception e) { 53 | LogUtil.e("R.id.rl_main_partner Unknown Error!"); 54 | } 55 | } 56 | 57 | if (XPrefUtils.getPref().getBoolean("tab4", false)) { 58 | //第四个按钮 59 | try { 60 | int rlMainTaskId = XposedHelpers.getStaticIntField(R$idClass, "rl_main_task"); 61 | RelativeLayout relativeLayout = mMainActivity.findViewById(rlMainTaskId); 62 | relativeLayout.setVisibility(View.GONE); 63 | } catch (Exception e) { 64 | LogUtil.e("R.id.rl_main_task Unknown Error!"); 65 | } 66 | } 67 | 68 | } 69 | 70 | @Override 71 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 72 | super.afterHookedMethod(param); 73 | } 74 | }); 75 | } 76 | 77 | @Override 78 | public boolean isOpen() { 79 | return true; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/DownloadPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.Constant; 4 | import com.lhy.xposed.mhzs.helper.LogUtil; 5 | 6 | import java.lang.reflect.Field; 7 | import java.util.List; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XposedHelpers; 11 | 12 | /** 13 | * download test 14 | * 15 | * @time 2019/03/13 pm 16 | */ 17 | @Deprecated 18 | public class DownloadPlugin implements IPlugin { 19 | private final String $DetailResponse = "com.mh.movie.core.mvp.model.entity.response.DetailResponse"; 20 | private final String $CacheView = "com.mh.movie.core.mvp.ui.widget.cache.CacheView"; 21 | 22 | @Override 23 | public void run(final ClassLoader classLoader) throws Throwable { 24 | // XposedHelpers.findAndHookMethod($DetailResponse, classLoader, "getDownloadBean", new XC_MethodHook() { 25 | // @Override 26 | // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 27 | // super.beforeHookedMethod(param); 28 | // LogUtil.e("====="); 29 | // 30 | // } 31 | // 32 | // @Override 33 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 34 | // super.afterHookedMethod(param); 35 | // } 36 | // }); 37 | // 38 | // XposedHelpers.findAndHookMethod($CacheView, classLoader, "b", 39 | // int.class, new XC_MethodHook() { 40 | // @Override 41 | // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 42 | // super.beforeHookedMethod(param); 43 | // Field u = XposedHelpers.findField(classLoader.loadClass($CacheView), "u"); 44 | // u.setAccessible(true); 45 | // u.setBoolean(param.thisObject, false); 46 | // 47 | // LogUtil.e("11111111111"); 48 | // } 49 | // 50 | // @Override 51 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 52 | // super.afterHookedMethod(param); 53 | // } 54 | // }); 55 | // XposedHelpers.findAndHookMethod(Constant.prst.$PlayerPresenter, classLoader, "a", 56 | // List.class, new XC_MethodHook() { 57 | // @Override 58 | // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 59 | // super.beforeHookedMethod(param); 60 | // LogUtil.e("222222222222"); 61 | // } 62 | // 63 | // @Override 64 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 65 | // super.afterHookedMethod(param); 66 | // } 67 | // }); 68 | } 69 | 70 | @Override 71 | public boolean isOpen() { 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/HideDanmuPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | 4 | import android.content.Context; 5 | 6 | import com.lhy.xposed.mhzs.helper.LogUtil; 7 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 8 | 9 | import java.lang.reflect.Method; 10 | import java.util.List; 11 | 12 | import de.robv.android.xposed.XC_MethodHook; 13 | import de.robv.android.xposed.XposedHelpers; 14 | 15 | /** 16 | * 默认隐藏弹幕 17 | *

18 | * 弹幕设置按钮可开启 19 | * 20 | * @author lhy 21 | * @time 2019年4月12日10:49:16 22 | */ 23 | public class HideDanmuPlugin implements IPlugin { 24 | private String $DanmakuVideoPlayer = "com.mh.movie.core.mvp.ui.activity.player.DanmakuVideoPlayer"; 25 | 26 | @Override 27 | public void run(final ClassLoader classLoader) throws Throwable { 28 | 29 | XposedHelpers.findAndHookMethod($DanmakuVideoPlayer, classLoader, "a", List.class, new XC_MethodHook() { 30 | @Override 31 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 32 | super.beforeHookedMethod(param); 33 | } 34 | 35 | @Override 36 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 37 | super.afterHookedMethod(param); 38 | XposedHelpers.callMethod(param.thisObject, "d"); 39 | } 40 | }); 41 | 42 | } 43 | 44 | @Override 45 | public boolean isOpen() { 46 | return XPrefUtils.getPref().getBoolean("hide_danmu", false); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/IPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | /** 4 | * 如果想对现有的插件进行扩展,请实现此方法 5 | *

6 | * 当然,您可以参照 TemplatePlugin 来开发 7 | *

8 | * 插件写完以后,在HookMain中的iPlugins数组,加入自己的插件即可 9 | */ 10 | public interface IPlugin { 11 | /** 12 | * 插件运行方法 13 | *

14 | * 请在此方法中进行Xposed Hook 15 | * 16 | * @param classLoader 17 | * @throws Throwable 18 | */ 19 | void run(ClassLoader classLoader) throws Throwable; 20 | 21 | /** 22 | * 插件的启用与关闭 23 | *

24 | * 1.可以直接返回true 或者 false 25 | * 2.可以添加配置文件,使用XPrefUtils.getPref().getBoolean("xxx", false)来返回结果 26 | * 27 | * @return 28 | */ 29 | boolean isOpen(); 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/InfiniteCachePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.util.Log; 4 | 5 | import com.lhy.xposed.mhzs.helper.LogUtil; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XposedHelpers; 11 | 12 | /** 13 | * @author lhy 14 | */ 15 | @Deprecated 16 | public class InfiniteCachePlugin implements IPlugin { 17 | 18 | private final String userInfoResponseClassName = "com.mh.movie.core.mvp.model.entity.response.UserInfoResponse"; 19 | private final String cacheViewClassName = "com.mh.movie.core.mvp.ui.widget.cache.CacheView"; 20 | private final String videoListBeanClassName = "com.mh.movie.core.mvp.model.entity.response.DetailResponse$VideoListBean"; 21 | 22 | @Override 23 | public void run(final ClassLoader classLoader) throws Throwable { 24 | XposedHelpers.findAndHookMethod(userInfoResponseClassName, classLoader, "getCanCacheNum", new XC_MethodHook() { 25 | @Override 26 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 27 | super.beforeHookedMethod(param); 28 | } 29 | 30 | @Override 31 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 32 | super.afterHookedMethod(param); 33 | LogUtil.e("Hook getRestCacheNum Method!"); 34 | param.setResult(-1); 35 | } 36 | }); 37 | 38 | XposedHelpers.findAndHookMethod(cacheViewClassName, classLoader, "b", int.class, new XC_MethodHook() { 39 | @Override 40 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 41 | super.beforeHookedMethod(param); 42 | LogUtil.e("--cache id--" + param.args[0]); 43 | } 44 | }); 45 | 46 | XposedHelpers.findAndHookMethod(videoListBeanClassName, classLoader, "getVideoState", new XC_MethodHook() { 47 | @Override 48 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 49 | super.afterHookedMethod(param); 50 | LogUtil.e("--getVideoState--" + param.getResult()); 51 | } 52 | }); 53 | 54 | XposedHelpers.findAndHookMethod(cacheViewClassName, classLoader, "a", boolean.class, int.class, classLoader.loadClass(videoListBeanClassName), new XC_MethodHook() { 55 | @Override 56 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 57 | super.beforeHookedMethod(param); 58 | Field yField = XposedHelpers.findField(classLoader.loadClass(cacheViewClassName), "y"); 59 | yField.setAccessible(true); 60 | yField.setInt(param.thisObject, 9); 61 | 62 | 63 | // int y = yField.getInt(param.thisObject); 64 | LogUtil.e("---" + param.args[0] + "---"); 65 | LogUtil.e("public void mo9800a(boolean z, int i, VideoListBean videoListBean) "); 66 | } 67 | }); 68 | 69 | 70 | } 71 | 72 | @Override 73 | public boolean isOpen() { 74 | return true; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/NoUpdatePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.Constant; 4 | import com.lhy.xposed.mhzs.helper.LogUtil; 5 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XposedBridge; 11 | import de.robv.android.xposed.XposedHelpers; 12 | 13 | /** 14 | * 去除主界面提示升级的对话框 15 | *

16 | * 该插件全版本通用 17 | * 18 | * @author lhy 19 | * @time 2019年2月27日16:22:31 20 | */ 21 | public class NoUpdatePlugin implements IPlugin { 22 | private final String channelResponseClassName = "com.mh.movie.core.mvp.model.entity.response.ChannelResponse"; 23 | 24 | @Override 25 | public void run(ClassLoader classLoader) throws Throwable { 26 | /** 27 | * 方法1:直接返回null 28 | */ 29 | // TODO: 2019/2/27 0027 与 EXP/VXP 可能会冲突 30 | // XposedHelpers.findAndHookMethod(channelResponseClassName, classLoader, "getUrl", new XC_MethodHook() { 31 | // @Override 32 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 33 | // super.afterHookedMethod(param); 34 | // LogUtil.e("Hook ChannelResponse!"); 35 | // param.setResult(null); 36 | // } 37 | // }); 38 | 39 | /** 40 | * 方法2:另辟蹊径 41 | * 42 | * 此变量名版本更新可能会改变 43 | */ 44 | final Class channelResponseClazz = classLoader.loadClass(channelResponseClassName); 45 | XposedHelpers.findAndHookMethod(Constant.act.$MainActivity, classLoader, "a", channelResponseClazz, new XC_MethodHook() { 46 | @Override 47 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 48 | super.afterHookedMethod(param); 49 | LogUtil.e("Hook MainActivity No Update!"); 50 | Object o = channelResponseClazz.cast(param.args[0]); 51 | XposedHelpers.findMethodBestMatch(channelResponseClazz, "setUrl", String.class); 52 | Method setUrlMethod = channelResponseClazz.getMethod("setUrl", String.class); 53 | setUrlMethod.invoke(o, ""); 54 | // XposedBridge.invokeOriginalMethod(setUrlMethod, o, new Object[]{""}); 55 | } 56 | }); 57 | } 58 | 59 | @Override 60 | public boolean isOpen() { 61 | return XPrefUtils.getPref().getBoolean("no_update", false); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/SharePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | 4 | import com.lhy.xposed.mhzs.helper.LogUtil; 5 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 6 | 7 | import java.lang.reflect.Method; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XC_MethodReplacement; 11 | import de.robv.android.xposed.XposedBridge; 12 | import de.robv.android.xposed.XposedHelpers; 13 | 14 | /** 15 | * 假装分享插件 16 | *

17 | * 点击即分享成功,将会取代WechatSharePlugin 18 | * 19 | * @author lhy 20 | * @time 2019年4月2日14:13:33 21 | */ 22 | 23 | 24 | public class SharePlugin implements IPlugin { 25 | private String $ShareManager = "com.mh.movie.core.c.a"; 26 | 27 | 28 | @Override 29 | public void run(final ClassLoader classLoader) throws Throwable { 30 | //分享成功所调用的方法 31 | /* 32 | mo2835x(); 33 | if (this.f2555s != null) { 34 | //参数f2538a代表以不同的方式分享 35 | // 1:微信朋友圈 2:微信 3:QQ 4:QQ空间 5:微博 36 | this.f2555s.mo2764d(this.f2538a); 37 | } 38 | */ 39 | 40 | //微信朋友圈 41 | XposedHelpers.findAndHookMethod($ShareManager, classLoader, "o", new XC_MethodReplacement() { 42 | @Override 43 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 44 | XposedHelpers.callMethod(param.thisObject, "x"); 45 | XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "s"), "d", 1); 46 | LogUtil.e("WeChat Friends share!"); 47 | return null; 48 | } 49 | }); 50 | 51 | //微信 52 | XposedHelpers.findAndHookMethod($ShareManager, classLoader, "p", new XC_MethodReplacement() { 53 | @Override 54 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 55 | XposedHelpers.callMethod(param.thisObject, "x"); 56 | XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "s"), "d", 2); 57 | LogUtil.e("WeChat share!"); 58 | return null; 59 | } 60 | }); 61 | 62 | //QQ 63 | XposedHelpers.findAndHookMethod($ShareManager, classLoader, "q", new XC_MethodReplacement() { 64 | @Override 65 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 66 | XposedHelpers.callMethod(param.thisObject, "x"); 67 | XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "s"), "d", 3); 68 | LogUtil.e("QQ share!"); 69 | return null; 70 | } 71 | }); 72 | 73 | //QQ空间 74 | XposedHelpers.findAndHookMethod($ShareManager, classLoader, "r", new XC_MethodReplacement() { 75 | @Override 76 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 77 | XposedHelpers.callMethod(param.thisObject, "x"); 78 | XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "s"), "d", 4); 79 | LogUtil.e("QQ Zone share!"); 80 | return null; 81 | } 82 | }); 83 | 84 | //微博 85 | XposedHelpers.findAndHookMethod($ShareManager, classLoader, "s", new XC_MethodReplacement() { 86 | @Override 87 | protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { 88 | XposedHelpers.callMethod(param.thisObject, "x"); 89 | XposedHelpers.callMethod(XposedHelpers.getObjectField(param.thisObject, "s"), "d", 5); 90 | LogUtil.e("WeiBo share!"); 91 | return null; 92 | } 93 | }); 94 | 95 | //QQ用户提供代码 96 | // try { 97 | // Class claz = XposedHelpers.findClass("com.mh.movie.core.mvp.ui.activity.player.PlayerActivity", classLoader); 98 | // Method m = claz.getDeclaredMethod("x"); 99 | // XposedBridge.log(m.getName()); 100 | // XposedHelpers.findAndHookMethod("com.mh.movie.core.mvp.ui.activity.player.PlayerActivity", classLoader, "x", new XC_MethodHook() { 101 | // 102 | // @Override 103 | // protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable { 104 | // super.beforeHookedMethod(param); 105 | // XposedBridge.log("微信分享开始替换"); 106 | // Class shareManagerClazz = XposedHelpers.findClass("com.mh.movie.core.c.a", classLoader); 107 | // Method shareManagerInstanceMethod = shareManagerClazz.getDeclaredMethod("i"); 108 | // Object shareManager = shareManagerInstanceMethod.invoke(null); 109 | // Method methodShareWeChat = shareManager.getClass().getDeclaredMethod("g"); 110 | // methodShareWeChat.invoke(shareManager); 111 | // // Method methodShareQQ = shareManager.getClass().getDeclaredMethod("a"); 112 | // // methodShareQQ.invoke(shareManager); 113 | // // Method methodShareWeiBo = shareManager.getClass().getDeclaredMethod("d"); 114 | // // methodShareWeiBo.invoke(shareManager); 115 | // param.setResult(null); 116 | // } 117 | // }); 118 | // } catch (Throwable e) { 119 | // XposedBridge.log("微信分享错误"); 120 | // XposedBridge.log(e.fillInStackTrace()); 121 | // } 122 | } 123 | 124 | @Override 125 | public boolean isOpen() { 126 | return XPrefUtils.getPref().getBoolean("share", false); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/TVPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.Button; 9 | import android.widget.LinearLayout; 10 | 11 | import com.lhy.xposed.mhzs.helper.Constant; 12 | import com.lhy.xposed.mhzs.helper.LogUtil; 13 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 14 | 15 | import java.lang.reflect.Field; 16 | 17 | import de.robv.android.xposed.XC_MethodHook; 18 | import de.robv.android.xposed.XposedHelpers; 19 | 20 | /** 21 | * TV投屏功能 22 | * @time 2019年3月10日 23 | * @author lhy 24 | */ 25 | public class TVPlugin implements IPlugin { 26 | @Override 27 | public void run(final ClassLoader classLoader) throws Throwable { 28 | 29 | XposedHelpers.findAndHookMethod(Constant.prst.$PlayerPresenter, classLoader, "c", int.class, new XC_MethodHook() { 30 | @Override 31 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 32 | super.beforeHookedMethod(param); 33 | } 34 | 35 | @Override 36 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 37 | super.afterHookedMethod(param); 38 | LogUtil.e("--TV Plugin--" + param.args[0]); 39 | if ((int) param.args[0] == 1 || (int) param.args[0] == 9) { 40 | Class tableCommodityClazz = classLoader.loadClass(Constant.db.$TableCommodity); 41 | Object object = tableCommodityClazz.newInstance(); 42 | Field hasFlag = XposedHelpers.findField(tableCommodityClazz, "hasFlag"); 43 | hasFlag.setAccessible(true); 44 | hasFlag.setInt(object, 1); 45 | Boolean b = XposedHelpers.getStaticBooleanField(classLoader.loadClass(Constant.act.$PlayerActivity), "q"); 46 | LogUtil.e("----" + b); 47 | param.setResult(object); 48 | } 49 | } 50 | }); 51 | } 52 | 53 | @Override 54 | public boolean isOpen() { 55 | return XPrefUtils.getPref().getBoolean("tv_screen", false); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/TemplatePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 4 | 5 | import de.robv.android.xposed.XC_MethodHook; 6 | import de.robv.android.xposed.XposedHelpers; 7 | 8 | /** 9 | * 这是一个插件开发模板 10 | */ 11 | public class TemplatePlugin implements IPlugin { 12 | 13 | /** 14 | * 请在此进行Hook 15 | * 16 | * @param classLoader 17 | * @throws Throwable 18 | */ 19 | @Override 20 | public void run(ClassLoader classLoader) throws Throwable { 21 | //Xposed框架的Hook方法 22 | XposedHelpers.findAndHookMethod("xxx", classLoader, "x", new XC_MethodHook() { 23 | @Override 24 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 25 | super.beforeHookedMethod(param); 26 | } 27 | 28 | @Override 29 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 30 | super.afterHookedMethod(param); 31 | } 32 | }); 33 | } 34 | 35 | /** 36 | * 插件的启用与关闭 37 | * 38 | * @return 39 | */ 40 | @Override 41 | public boolean isOpen() { 42 | // return false; 43 | return XPrefUtils.getPref().getBoolean("xxx", false); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/WatchThirtyMinutesPlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.content.Context; 6 | import android.content.SharedPreferences; 7 | 8 | import com.lhy.xposed.mhzs.helper.Constant; 9 | import com.lhy.xposed.mhzs.helper.LogUtil; 10 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 11 | 12 | import java.util.Timer; 13 | import java.util.TimerTask; 14 | 15 | import de.robv.android.xposed.XC_MethodHook; 16 | import de.robv.android.xposed.XposedHelpers; 17 | 18 | /** 19 | * 观看30分钟任务 插件 20 | *

21 | * 播放任意一部影片即可完成任务 22 | * 23 | * @author lhy 24 | * @time 2019年3月14日17:06:50 25 | */ 26 | public class WatchThirtyMinutesPlugin implements IPlugin { 27 | @Override 28 | public void run(ClassLoader classLoader) throws Throwable { 29 | 30 | // XposedHelpers.findAndHookMethod(Constant.$MHApplication, classLoader, "onCreate", 31 | // new XC_MethodHook() { 32 | // @Override 33 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 34 | // super.afterHookedMethod(param); 35 | // Application application = (Application) param.thisObject; 36 | // SharedPreferences sp = application.getSharedPreferences("config", Context.MODE_PRIVATE); 37 | // sp.edit().putLong("total_time", 1800002).commit(); 38 | // LogUtil.e("Hook Movie Time"); 39 | // } 40 | // }); 41 | // 42 | // XposedHelpers.findAndHookMethod(Timer.class.getName(), classLoader, "schedule", TimerTask.class, 43 | // long.class, long.class, new XC_MethodHook() { 44 | // @Override 45 | // protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 46 | // super.beforeHookedMethod(param); 47 | // long delay = (long) param.args[1]; 48 | // long period = (long) param.args[2]; 49 | // if (delay == 180000 && period == 180000) { 50 | // param.args[1] = 0; 51 | // } 52 | // } 53 | // 54 | // @Override 55 | // protected void afterHookedMethod(MethodHookParam param) throws Throwable { 56 | // super.afterHookedMethod(param); 57 | // } 58 | // }); 59 | 60 | XposedHelpers.findAndHookMethod(Constant.act.$PlayerActivity, classLoader, "j", new XC_MethodHook() { 61 | @Override 62 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 63 | super.beforeHookedMethod(param); 64 | } 65 | 66 | @Override 67 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 68 | super.afterHookedMethod(param); 69 | 70 | /*源代码 71 | if (RecordUtils.getTotalTime(PlayerActivity.this).longValue() >= 1800000) { 72 | ((PlayerPresenter) PlayerActivity.this.b).mo6407s(); 73 | } 74 | */ 75 | Activity activity = (Activity) param.thisObject; 76 | Object pres = XposedHelpers.getObjectField(activity, "b"); 77 | XposedHelpers.callMethod(pres, "s"); 78 | LogUtil.e("task 30"); 79 | } 80 | }); 81 | } 82 | 83 | @Override 84 | public boolean isOpen() { 85 | return XPrefUtils.getPref().getBoolean("thirty_task", false); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /app/src/main/java/com/lhy/xposed/mhzs/plugin/WechatSharePlugin.java: -------------------------------------------------------------------------------- 1 | package com.lhy.xposed.mhzs.plugin; 2 | 3 | import com.lhy.xposed.mhzs.helper.Constant; 4 | import com.lhy.xposed.mhzs.helper.LogUtil; 5 | import com.lhy.xposed.mhzs.helper.XPrefUtils; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | import de.robv.android.xposed.XC_MethodHook; 10 | import de.robv.android.xposed.XposedBridge; 11 | import de.robv.android.xposed.XposedHelpers; 12 | 13 | /** 14 | * 强制微信分享成功 15 | *

16 | * (不完美) 17 | * 18 | * @author lhy 19 | * @time 2019年2月17日12:18:26 20 | *

21 | * 2019年3月12日11:07:58 开启测试 22 | */ 23 | public class WechatSharePlugin implements IPlugin { 24 | 25 | // private final String detailResponseClassName = "com.mh.movie.core.mvp.model.entity.response.DetailResponse$VideoListBean"; 26 | // private final String playerPresenterClassName = "com.mh.movie.core.mvp.presenter.player.PlayerPresenter"; 27 | // private final String wxShareClassName = "com.amahua.share.e"; 28 | // private final String wxShareBroadReceiverClassName = "com.amahua.share.e$a"; 29 | // private final String playerActivityClassName = "com.mh.movie.core.mvp.ui.activity.player.PlayerActivity"; 30 | 31 | // private final String wXEntryActivityClassName = "com.amahua.ompimdrt.wxapi.WXEntryActivity"; 32 | private final String baseRespClassName = "com.tencent.mm.opensdk.modelbase.BaseResp"; 33 | 34 | @Override 35 | public void run(final ClassLoader classLoader) throws Throwable { 36 | 37 | try { 38 | watchHotMovie(classLoader); 39 | } catch (ClassNotFoundException e) { 40 | LogUtil.e("BaseResp NotFound!"); 41 | XposedBridge.log(e); 42 | } catch (Exception e) { 43 | LogUtil.e("watchHotMovie Unknown Error"); 44 | XposedBridge.log(e); 45 | } 46 | 47 | 48 | } 49 | 50 | private void watchHotMovie(final ClassLoader classLoader) throws ClassNotFoundException { 51 | 52 | final Class baseRespClazz = classLoader.loadClass(baseRespClassName); 53 | 54 | /** 55 | * 方法1: 56 | * 改变分享结果 57 | */ 58 | XposedHelpers.findAndHookMethod(Constant.act.$WXEntryActivity, classLoader, "onResp", baseRespClazz, new XC_MethodHook() { 59 | @Override 60 | protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 61 | 62 | // Constructor constructors[] = baseRespClazz.getConstructors(); 63 | // for (Constructor constructor : constructors) { 64 | // LogUtil.e(constructor + "--"); 65 | // } 66 | // 67 | // Field fields[] = baseRespClazz.getFields(); 68 | // for (Field field : fields) { 69 | // LogUtil.e(field + "--"); 70 | // } 71 | 72 | Field field = baseRespClazz.getField("errCode"); 73 | field.setAccessible(true); 74 | field.setInt(param.args[0], 0); 75 | LogUtil.e("errCode = " + field.getInt(param.args[0])); 76 | 77 | super.beforeHookedMethod(param); 78 | } 79 | 80 | @Override 81 | protected void afterHookedMethod(MethodHookParam param) throws Throwable { 82 | super.afterHookedMethod(param); 83 | } 84 | }); 85 | 86 | /** 87 | * 无效的方法 88 | */ 89 | // XposedHelpers.findAndHookMethod(playerActivityClassName, classLoader, "v", new XC_MethodReplacement() { 90 | // @Override 91 | // protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { 92 | // 93 | //// Constructor constructor = XposedHelpers.findConstructorBestMatch(baseRespClazz); 94 | //// Object baseRespObject = constructor.newInstance(); 95 | ////// Object baseRespObject = baseRespClazz.newInstance(); 96 | //// Field errCodeField = baseRespClazz.getField("errCode"); 97 | //// errCodeField.setAccessible(true); 98 | //// errCodeField.setInt(baseRespObject, 0); 99 | //// 100 | //// Class[] parameterTypes = {baseRespClazz}; 101 | //// Constructor constructor2 = responseClazz.getConstructor(parameterTypes); 102 | //// Object[] parameters = {baseRespObject}; 103 | //// Object responseObject = constructor2.newInstance(parameters); 104 | // 105 | // Object responseObject = responseClazz.newInstance(); 106 | // Field errCodeField = responseClazz.getField("a"); 107 | // errCodeField.setAccessible(true); 108 | // errCodeField.setInt(responseObject, 0); 109 | // Parcelable parcelable = (Parcelable) responseClazz.cast(responseObject); 110 | // 111 | // Activity mActivity = (Activity) methodHookParam.thisObject; 112 | // Intent intent = new Intent("action_wx_share_response"); 113 | // intent.putExtra("result", parcelable); 114 | // mActivity.sendBroadcast(intent); 115 | // return null; 116 | // } 117 | // }); 118 | } 119 | 120 | 121 | @Override 122 | public boolean isOpen() { 123 | return XPrefUtils.getPref().getBoolean("wechat_share", true); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_focused_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_focused_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_pressed_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_off_pressed_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_focused_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_focused_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_pressed_holo_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_btn_check_on_pressed_holo_light.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_close_bg_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_close_bg_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bmob_update_close_bg_tap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable-hdpi/bmob_update_close_bg_tap.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_cancel_bg_focused.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_cancel_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_cancel_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_cancel_bg_tap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_check_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 9 | 10 | 13 | 16 | 17 | 20 | 23 | 24 | 27 | 30 | 31 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_close_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_ok_bg_focused.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_ok_bg_normal.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_ok_bg_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_button_ok_bg_tap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bmob_update_wifi_disable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1595901624/mhzs/e952afef1768126e89eed9ee72cbb8a47bbe1a0c/app/src/main/res/drawable/bmob_update_wifi_disable.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/submit_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 19 | 20 | 24 | 25 | 31 | 32 | 36 | 37 | 44 | 45 | 52 | 53 | 60 | 61 | 62 | 63 | 77 | 78 | 92 | 93 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_ad.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_feedback.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 19 | 20 | 25 | 26 | 33 | 34 | 40 | 41 | 48 | 49 | 56 | 57 |