├── .gitattributes ├── .github └── workflows │ └── app.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle.kts ├── dict.txt ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── xposed_init │ ├── ic_launcher-playstore.png │ ├── java │ └── com │ │ └── weverses │ │ └── modempro │ │ ├── activity │ │ └── MainActivity.kt │ │ ├── hook │ │ ├── MainHook.kt │ │ └── hooks │ │ │ ├── BaseHook.kt │ │ │ ├── android │ │ │ ├── Check.kt │ │ │ ├── DSDA.kt │ │ │ ├── DualDataSupport.kt │ │ │ ├── DualNRSupport.kt │ │ │ ├── DualSASupport.kt │ │ │ ├── FiveGSwitch.kt │ │ │ ├── N1Band.kt │ │ │ ├── N28Band.kt │ │ │ ├── N5N8Band.kt │ │ │ └── Optimization.kt │ │ │ ├── mtb │ │ │ └── BypassAuthentication.kt │ │ │ └── phone │ │ │ ├── BandCondition.kt │ │ │ ├── Check.kt │ │ │ ├── DisableCrbtSupport.kt │ │ │ ├── DsdaSupport.kt │ │ │ ├── DualData.kt │ │ │ ├── DualNrSupport.kt │ │ │ ├── DualSaSupport.kt │ │ │ ├── DualdataConcurrent.kt │ │ │ ├── DualdataRedundant.kt │ │ │ ├── FiveGSwitch.kt │ │ │ ├── HikingCity.kt │ │ │ ├── ModemFeature.kt │ │ │ ├── N1BandPhone.kt │ │ │ ├── N28BandPhone.kt │ │ │ ├── N5N8BandPhone.kt │ │ │ ├── OptimizationSupport.kt │ │ │ ├── SmartCallForwardSupport.kt │ │ │ └── ViceSlotVolteButton.kt │ │ └── util │ │ ├── Check.kt │ │ ├── Utils.kt │ │ └── getPackageNames.kt │ └── res │ ├── drawable │ ├── author.jpg │ ├── ic_icon.png │ └── ic_launcher.xml │ ├── values-ja │ └── strings.xml │ ├── values-night │ └── themes.xml │ ├── values-zh-rCN │ └── strings.xml │ ├── values-zh-rHK │ └── strings.xml │ ├── values-zh-rMO │ └── strings.xml │ ├── values-zh-rSG │ └── strings.xml │ ├── values-zh-rTW │ └── strings.xml │ └── values │ ├── array.xml │ ├── colors.xml │ ├── strings.xml │ └── themes.xml ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── version.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/app.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ "dev" ] 6 | paths-ignore: 7 | - 'README.md' 8 | pull_request: 9 | branches: [ "dev" ] 10 | 11 | jobs: 12 | build: 13 | 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | 18 | - uses: actions/checkout@v2 19 | with: 20 | submodules: 'recursive' 21 | 22 | - name: set up JDK 17 23 | uses: actions/setup-java@v3 24 | with: 25 | java-version: '17' 26 | distribution: 'temurin' 27 | cache: gradle 28 | 29 | - uses: actions/cache@v2 30 | with: 31 | path: | 32 | ~/.gradle/caches 33 | ~/.gradle/wrapper 34 | !~/.gradle/caches/build-cache-* 35 | key: gradle-deps-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} 36 | restore-keys: gradle-deps 37 | 38 | - uses: actions/cache@v2 39 | with: 40 | path: | 41 | ~/.gradle/caches/build-cache-* 42 | key: gradle-builds-${{ github.sha }} 43 | 44 | - name: Build with Gradle 45 | run: | 46 | echo ${{ secrets.SIGNING_KEY }} | base64 -d > keystore.jks 47 | bash ./gradlew assemble 48 | env: 49 | KEYSTORE_PATH: "../keystore.jks" 50 | KEYSTORE_PASS: ${{ secrets.KEY_STORE_PASSWORD }} 51 | KEY_ALIAS: ${{ secrets.KEY_ALIAS }} 52 | KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} 53 | 54 | - name: prepare upload 55 | run: | 56 | getDate=$(TZ=UTC-8 date +%Y-%m-%d) 57 | getVersion=$(cat ~/work/ModemPro/ModemPro/version.txt) 58 | echo "date=$getDate" >> $GITHUB_ENV 59 | echo "version=$getVersion" >> $GITHUB_ENV 60 | echo "name=ModemPro_'$getVersion'_'$getDate'" >> $GITHUB_ENV 61 | mv ~/work/ModemPro/ModemPro/app/build/outputs/apk/debug/*.apk ~/work/ModemPro/ModemPro/app/build/outputs/apk/debug/ModemPro_"$getVersion"_"$getDate"_debug.apk 62 | mv ~/work/ModemPro/ModemPro/app/build/outputs/apk/release/*.apk ~/work/ModemPro/ModemPro/app/build/outputs/apk/release/ModemPro_"$getVersion"_"$getDate"_release.apk 63 | mkdir -p ~/work/ModemPro/ModemPro/GithubRelease 64 | cp ~/work/ModemPro/ModemPro/app/build/outputs/apk/debug/*.apk ~/work/ModemPro/ModemPro/GithubRelease 65 | cp ~/work/ModemPro/ModemPro/app/build/outputs/apk/release/*.apk ~/work/ModemPro/ModemPro/GithubRelease 66 | touch /home/runner/work/ModemPro/ModemPro/file.log 67 | echo "ModemPro_$getVersion_$getDate" > /home/runner/work/ModemPro/ModemPro/file.log 68 | 69 | - name: Upload Github Release 70 | uses: ncipollo/release-action@main 71 | with: 72 | artifacts: ~/work/ModemPro/ModemPro/GithubRelease/* 73 | name: "${{ env.version }}" 74 | tag: "${{ env.version }}" 75 | bodyFile: /home/runner/work/ModemPro/ModemPro/file.log 76 | allowUpdates: true 77 | artifactErrorsFailBuild: true 78 | token: ${{ secrets.GITHUB_TOKEN }} 79 | 80 | - name: Upload release 81 | uses: actions/upload-artifact@v2 82 | with: 83 | name: ModemPro_Release 84 | path: "app/build/outputs/apk/release/*.apk" 85 | 86 | - name: Upload debug 87 | uses: actions/upload-artifact@v2 88 | with: 89 | name: ModemPro_Debug 90 | path: "app/build/outputs/apk/debug/*.apk" 91 | 92 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | .cxx 10 | local.properties 11 | /app/release 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "blockmiui"] 2 | path = blockmiui 3 | url = https://github.com/Block-Network/blockmiui.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # ModemPro 基带进化 4 | 5 | 这是一个适用于MIUI 13/14的基带增强型Xposed模块 6 | 7 | Android CI Github Releases GitHub all releases GitHub stars GitHub issues GitHub license 8 | 9 |
10 | 11 | ## 功能 12 | - 为基带版本基带版本≥2.5.0的865/870机型增加双卡5G支持 13 | - 解锁N5/N8/N28频段支持 14 | - 智能双卡切换 15 | - 副卡VoLTE通话时可联网 16 | - 解锁MTB的开发权限限制 17 | 18 | ## 设备/系统要求 19 | - 是小米/Redmi手机,非sgsi/gsi 20 | - Android版本≥12, MIUI版本≥13 21 | 22 | ## 使用方法 23 | - 在LSPosed仓库内下载并安装 24 | - 在LSPosed App内开启本模块,并勾选所有的推荐作用域 25 | - 开启/关闭你需要的功能 26 | - 重启手机后即可享用 27 | 28 | ## 已知问题 29 | - 解锁N5/N5/N28频段后实际可能因为信令不上报导致无效,如果有大佬能解决欢迎pr 30 | 31 | ## 注意事项 32 | - 因为副卡为5G NSA,系统不会优先连接,请自行在拨号盘输入*#*#4636#*#*锁定NR 33 | - 请勾选全部的作用域,否则可能出现在设置里没有双卡5G开关的问题 34 | 35 | ## 下载 36 | - Github Action: https://github.com/Weverses/ModemPro/actions 37 | - Github Releases: https://github.com/Xposed-Modules-Repo/com.weverses.modempro/releases/ 38 | - Xposed Modules Repo: https://modules.lsposed.org/module/com.weverses.modempro 39 | 40 | ## 第三方开源引用 41 | - GNU Lesser General Public License v2.1 42 | [577fkj/blockmiui](https://github.com/577fkj/blockmiui) 43 | - Apache License 2.0 44 | [KyuubiRan/EzXHelper](https://github.com/KyuubiRan/EzXHelper) 45 | 46 | ## License 47 | [GNU General Public License v3.0](https://github.com/Weverses/ModemPro/blob/main/LICENSE) 48 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import java.util.Properties 2 | 3 | 4 | plugins { 5 | id("com.android.application") 6 | id("org.jetbrains.kotlin.android") 7 | } 8 | 9 | android { 10 | compileSdk = 34 11 | 12 | defaultConfig { 13 | applicationId = "com.weverses.modempro" 14 | minSdk = 29 15 | targetSdk = 34 16 | versionCode = 220 17 | versionName = "2.2.0" 18 | } 19 | 20 | val properties = Properties() 21 | runCatching { properties.load(project.rootProject.file("local.properties").inputStream()) } 22 | val keystorePath = properties.getProperty("KEYSTORE_PATH") ?: System.getenv("KEYSTORE_PATH") 23 | val keystorePwd = properties.getProperty("KEYSTORE_PASS") ?: System.getenv("KEYSTORE_PASS") 24 | val alias = properties.getProperty("KEY_ALIAS") ?: System.getenv("KEY_ALIAS") 25 | val pwd = properties.getProperty("KEY_PASSWORD") ?: System.getenv("KEY_PASSWORD") 26 | if (keystorePath != null) { 27 | signingConfigs { 28 | create("release") { 29 | storeFile = file(keystorePath) 30 | storePassword = keystorePwd 31 | keyAlias = alias 32 | keyPassword = pwd 33 | enableV3Signing = true 34 | } 35 | } 36 | } 37 | 38 | buildTypes { 39 | release { 40 | isShrinkResources = true 41 | isMinifyEnabled = true 42 | proguardFiles("proguard-rules.pro") 43 | if (keystorePath != null) { 44 | signingConfig = signingConfigs.getByName("release") 45 | } 46 | } 47 | debug { 48 | if (keystorePath != null) { 49 | signingConfig = signingConfigs.getByName("release") 50 | } 51 | } 52 | } 53 | 54 | androidResources { 55 | additionalParameters("--allow-reserved-package-id", "--package-id", "0x45") 56 | } 57 | 58 | packagingOptions { 59 | resources { 60 | excludes += "/META-INF/**" 61 | excludes += "/kotlin/**" 62 | excludes += "/*.txt" 63 | excludes += "/*.bin" 64 | } 65 | } 66 | 67 | compileOptions { 68 | sourceCompatibility = JavaVersion.VERSION_11 69 | targetCompatibility = JavaVersion.VERSION_11 70 | } 71 | kotlinOptions { 72 | jvmTarget = JavaVersion.VERSION_11.toString() 73 | } 74 | namespace = "com.weverses.modempro" 75 | } 76 | 77 | dependencies { 78 | implementation(project(":blockmiui")) 79 | implementation("com.github.kyuubiran:EzXHelper:2.0.8") 80 | implementation("androidx.core:core-ktx:+") 81 | compileOnly("de.robv.android.xposed:api:82") 82 | } 83 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -keep class com.weverses.modempro.hook.MainHook -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 19 | 22 | 25 | 28 | 29 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/assets/xposed_init: -------------------------------------------------------------------------------- 1 | com.weverses.modempro.hook.MainHook -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Weverses/ModemPro/74d38bdf067708a9894bfc15c86873a52c7b3c3d/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/activity/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.activity 2 | 3 | import android.annotation.SuppressLint 4 | import android.content.Intent 5 | import android.net.Uri 6 | import android.os.Bundle 7 | import cn.fkj233.ui.activity.MIUIActivity 8 | import cn.fkj233.ui.activity.view.SwitchV 9 | import cn.fkj233.ui.activity.view.TextSummaryV 10 | import cn.fkj233.ui.dialog.MIUIDialog 11 | import com.weverses.modempro.R 12 | import com.weverses.modempro.util.Check 13 | import com.weverses.modempro.util.Check.DualdataDevices 14 | import com.weverses.modempro.util.Check.getAndroidVersion 15 | import com.weverses.modempro.util.Check.getMIUIVersion 16 | import com.weverses.modempro.util.Check.isMTK 17 | import com.weverses.modempro.util.Check.isUnSupportedMIUIVersion 18 | import com.weverses.modempro.util.Check.iskonaPlatform 19 | import com.weverses.modempro.util.Check.islahainaPlatform 20 | import com.weverses.modempro.util.Check.istaroPlatform 21 | import com.weverses.modempro.util.Utils 22 | import com.weverses.modempro.util.Utils.isSupportDevices 23 | import com.weverses.modempro.util.getPackageNames 24 | import kotlin.system.exitProcess 25 | 26 | class MainActivity : MIUIActivity() { 27 | // 根据默认是否支持来显示开关,不会有人想关功能的吧:) 28 | // byd 先不启用 29 | val isN5Support = false 30 | val isN8Support = false 31 | val isN28Support = false 32 | val NR = false 33 | val SA = false 34 | override fun onCreate(savedInstanceState: Bundle?) { 35 | checkLSPosed() 36 | checkMTK() 37 | checkMIUIVersion() 38 | val packageManager = applicationContext.packageManager 39 | val allPackageNames = getPackageNames.getAllAppPackageNames(packageManager) 40 | super.onCreate(savedInstanceState) 41 | } 42 | 43 | 44 | @SuppressLint("WorldReadableFiles") 45 | private fun checkLSPosed() { 46 | try { 47 | setSP(getSharedPreferences("config", MODE_WORLD_READABLE)) 48 | } catch (exception: SecurityException) { 49 | isLoad = false 50 | MIUIDialog(this) { 51 | setTitle(R.string.warning) 52 | setMessage(R.string.not_support) 53 | setCancelable(false) 54 | setRButton(R.string.done) { 55 | exitProcess(0) 56 | } 57 | }.show() 58 | } 59 | } 60 | 61 | private fun checkMTK() { 62 | if (isMTK()) { 63 | MIUIDialog(this) { 64 | setTitle(R.string.tips) 65 | setMessage(R.string.mtk_device) 66 | setCancelable(false) 67 | setRButton(R.string.done) { 68 | dismiss() 69 | } 70 | }.show() 71 | } 72 | } 73 | 74 | private fun checkMIUIVersion() { 75 | if (isUnSupportedMIUIVersion()) { 76 | MIUIDialog(this) { 77 | setTitle(R.string.tips) 78 | setMessage(R.string.antique_version) 79 | setCancelable(false) 80 | setRButton(R.string.done) { 81 | dismiss() 82 | } 83 | }.show() 84 | } 85 | } 86 | 87 | init { 88 | initView { 89 | registerMain(getString(R.string.app_title), false) { 90 | TitleText(textId = R.string.title_tips) 91 | if (getMIUIVersion() > 14f) { 92 | TextSummaryWithSwitch( 93 | TextSummaryV( 94 | textId = R.string.fiveg_switch_title, 95 | tipsId = R.string.fiveg_switch_summary 96 | ), 97 | SwitchV("fiveg_switch", true) 98 | ) 99 | } 100 | if (iskonaPlatform() && !isUnSupportedMIUIVersion()) { 101 | TitleText(textId = R.string.title1) 102 | TextSummaryWithSwitch( 103 | TextSummaryV( 104 | textId = R.string.dual_nr_title, 105 | tipsId = R.string.dual_nr_summary 106 | ), 107 | SwitchV("dual_nr", true) 108 | ) 109 | 110 | Line() 111 | TitleText(textId = R.string.title2) 112 | TextSummaryWithSwitch( 113 | TextSummaryV( 114 | textId = R.string.n28_title, 115 | tipsId = R.string.n28_summary 116 | ), 117 | SwitchV("n28_band", true) 118 | ) 119 | TextSummaryWithSwitch( 120 | TextSummaryV( 121 | textId = R.string.n5_n8_title, 122 | tipsId = R.string.n5_n8_summary 123 | ), 124 | SwitchV("n5_n8_band", true) 125 | ) 126 | } 127 | 128 | if (!isSupportDevices(DualdataDevices) && !isUnSupportedMIUIVersion()) { 129 | Line() 130 | TitleText(textId = R.string.title6) 131 | TextSummaryWithSwitch( 132 | TextSummaryV( 133 | textId = R.string.smart_dual_sim_title, 134 | tipsId = R.string.smart_dual_sim_summary 135 | ), 136 | SwitchV("vice_slot_volte", true) 137 | ) 138 | 139 | TextA( 140 | textId = R.string.vice_slot_volte_title, 141 | onClickListener = { 142 | MIUIDialog(this@MainActivity) { 143 | setTitle(R.string.vice_slot_volte_title) 144 | setMessage(R.string.vice_slot_volte_summary) 145 | setLButton(R.string.disable) { 146 | Utils.exec("settings put global vice_slot_volte_data_enabled 0") 147 | dismiss() 148 | } 149 | setRButton(R.string.enable) { 150 | Utils.exec("settings put global vice_slot_volte_data_enabled 1") 151 | dismiss() 152 | } 153 | }.show() 154 | } 155 | ) 156 | } 157 | 158 | if (!isMTK()) { 159 | Line() 160 | TitleText(textId = R.string.title3) 161 | TextSummaryWithSwitch( 162 | TextSummaryV( 163 | textId = R.string.mtb_auth_title, 164 | tipsId = R.string.mtb_auth_summary 165 | ), 166 | SwitchV("mtb_auth", false) 167 | ) 168 | } 169 | 170 | if (islahainaPlatform()) { 171 | if (getMIUIVersion() < 15f || getAndroidVersion() < "14") { 172 | Line() 173 | TitleText(textId = R.string.title4) 174 | } 175 | TextSummaryWithSwitch( 176 | TextSummaryV( 177 | textId = R.string.dual_sa_title, 178 | tipsId = R.string.dual_sa_summary 179 | ), 180 | SwitchV("dual_sa", false) 181 | ) 182 | } 183 | 184 | // val mDualData = sharedPreferences.getBoolean("mDualData", false) 185 | if (isSupportDevices(DualdataDevices) || getMIUIVersion() > 14f || getAndroidVersion() > "13"){ 186 | Line() 187 | TitleText(textId = R.string.title8) 188 | TitleText(textId = R.string.title8_tips) 189 | TextSummaryWithSwitch( 190 | TextSummaryV( 191 | textId = R.string.smart_dual_data_title, 192 | tipsId = R.string.smart_dual_data_summary 193 | ), 194 | SwitchV("dual_data", false) 195 | ) 196 | 197 | TextSummaryWithSwitch( 198 | TextSummaryV( 199 | textId = R.string.opt_title, 200 | tipsId = R.string.opt_summary 201 | ), 202 | SwitchV("opt", false) 203 | ) 204 | 205 | TextSummaryWithSwitch( 206 | TextSummaryV( 207 | textId = R.string.hiking_title, 208 | tipsId = R.string.hiking_summary 209 | ), 210 | SwitchV("hiking_city", false) 211 | ) 212 | 213 | TextA( 214 | textId = R.string.concurrent_title, 215 | onClickListener = { 216 | MIUIDialog(this@MainActivity) { 217 | setTitle(R.string.tips) 218 | setMessage(R.string.concurrent_summary) 219 | setLButton(R.string.disable) { 220 | Utils.exec("settings put global dual_data_concurrent_mode_white_list_pkg_name com.android.providers.downloads.ui,com.ss.android.ugc.aweme,com.android.providers.downloads,tv.danmaku.bili,com.xiaomi.market,org.zwanoo.android.speedtest") 221 | safeSP.putAny("concurrent","false") 222 | dismiss() 223 | } 224 | setRButton(R.string.enable) { 225 | val packageManager = applicationContext.packageManager 226 | val allPackageNames = getPackageNames.getAllThirdPartyAppPackageNames(packageManager) 227 | Utils.exec("settings put global dual_data_concurrent_mode_white_list_pkg_name ${allPackageNames}") 228 | safeSP.putAny("concurrent","true") 229 | dismiss() 230 | } 231 | }.show() 232 | } 233 | ) 234 | 235 | TextA( 236 | textId = R.string.redundant_title, 237 | onClickListener = { 238 | MIUIDialog(this@MainActivity) { 239 | setTitle(R.string.tips) 240 | setMessage(R.string.redundant_summary) 241 | setLButton(R.string.disable) { 242 | Utils.exec("settings put global dual_data_redundant_mode_white_list_pkg_name com.tencent.tmgp.sgame,com.tencent.tmgp.pubgmhd") 243 | safeSP.putAny("redundant","true") 244 | dismiss() 245 | } 246 | setRButton(R.string.enable) { 247 | val packageManager = applicationContext.packageManager 248 | val allPackageNames = getPackageNames.getAllThirdPartyAppPackageNames(packageManager) 249 | Utils.exec("settings put global dual_data_redundant_mode_white_list_pkg_name ${allPackageNames}") 250 | safeSP.putAny("redundant","true") 251 | dismiss() 252 | } 253 | }.show() 254 | } 255 | ) 256 | 257 | Line() 258 | TitleText(textId = R.string.title4) 259 | 260 | TextSummaryWithSwitch( 261 | TextSummaryV( 262 | textId = R.string.dual_data_bands_title, 263 | tipsId = R.string.dual_data_bands_summary 264 | ), 265 | SwitchV("dualdata_bands", false) 266 | ) 267 | 268 | TextSummaryWithSwitch( 269 | TextSummaryV( 270 | textId = R.string.smart_call_forward_title, 271 | tipsId = R.string.smart_call_forward_summary 272 | ), 273 | SwitchV("smart_call_forward", false) 274 | ) 275 | 276 | TextSummaryWithSwitch( 277 | TextSummaryV( 278 | textId = R.string.disable_crbt_title, 279 | tipsId = R.string.disable_crbt_summary 280 | ), 281 | SwitchV("disable_crbt", false) 282 | ) 283 | } 284 | 285 | Line() 286 | TitleText(textId = R.string.about) 287 | Author( 288 | getDrawable(R.drawable.author)!!, "Weverse", "Hook,Icon...more" , 289 | onClickListener = { 290 | MIUIDialog(this@MainActivity) { 291 | setTitle(R.string.author_title) 292 | setMessage(R.string.love) 293 | setLButton(R.string.author_description) { 294 | val uri = Uri.parse("http://www.coolapk.com/u/18895441") 295 | val author = Intent(Intent.ACTION_VIEW, uri) 296 | startActivity(author) 297 | } 298 | setRButton(R.string.love_url) { 299 | val love = Uri.parse("https://afdian.net/a/Weverse") 300 | val intent = Intent(Intent.ACTION_VIEW, love) 301 | startActivity(intent) 302 | } 303 | }.show() 304 | } 305 | ) 306 | 307 | Line() 308 | TitleText(textId = R.string.title5) 309 | TextA( 310 | textId = R.string.reboot_system, 311 | onClickListener = { 312 | MIUIDialog(this@MainActivity) { 313 | setTitle(R.string.warning) 314 | setMessage(R.string.reboot_tips) 315 | setLButton(R.string.cancel) { 316 | dismiss() 317 | } 318 | setRButton(R.string.done) { 319 | Utils.exec("/system/bin/sync;/system/bin/svc power reboot || reboot") 320 | } 321 | }.show() 322 | } 323 | ) 324 | } 325 | } 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/MainHook.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook 2 | 3 | import com.github.kyuubiran.ezxhelper.EzXHelper 4 | import com.github.kyuubiran.ezxhelper.Log 5 | import com.github.kyuubiran.ezxhelper.LogExtensions.logexIfThrow 6 | import com.weverses.modempro.hook.hooks.BaseHook 7 | import com.weverses.modempro.hook.hooks.android.* 8 | import com.weverses.modempro.hook.hooks.android.FiveGSwitch 9 | import com.weverses.modempro.hook.hooks.mtb.* 10 | import com.weverses.modempro.hook.hooks.phone.* 11 | import com.weverses.modempro.util.Utils 12 | import de.robv.android.xposed.IXposedHookLoadPackage 13 | import de.robv.android.xposed.callbacks.XC_LoadPackage 14 | 15 | private const val TAG = "ModemPro" 16 | private val PACKAGE_NAME_HOOKED = setOf( 17 | "android", "com.android.phone", "com.xiaomi.mtb" 18 | ) 19 | 20 | class MainHook : IXposedHookLoadPackage { 21 | override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) { 22 | if (lpparam.packageName in PACKAGE_NAME_HOOKED) { 23 | // Init EzXHelper 24 | EzXHelper.initHandleLoadPackage(lpparam) 25 | EzXHelper.setLogTag(TAG) 26 | EzXHelper.setToastTag(TAG) 27 | // Init hooks 28 | when (lpparam.packageName) { 29 | "android" -> { 30 | // initHooks(Check) 31 | if (Utils.getBoolean("dual_nr", true)) { 32 | initHooks(DualNRSupport) 33 | } 34 | if (Utils.getBoolean("dual_sa", true)) { 35 | initHooks(DualSASupport) 36 | } 37 | if (Utils.getBoolean("n1_band", true)) { 38 | initHooks(N1Band) 39 | } 40 | if (Utils.getBoolean("n28_band", true)) { 41 | initHooks(N28Band) 42 | } 43 | if (Utils.getBoolean("n5_n8_band", true)) { 44 | initHooks(N5N8Band) 45 | } 46 | if (Utils.getBoolean("opt", false)) { 47 | initHooks(Optimization) 48 | } 49 | if (Utils.getBoolean("dualdata", false)) { 50 | initHooks(DualData) 51 | // initHooks(DSDA) 52 | } 53 | if (Utils.getBoolean("fiveg_switch", false)) { 54 | initHooks(FiveGSwitch) 55 | } 56 | } 57 | "com.android.phone" -> { 58 | // initHooks(Check) 59 | if (Utils.getBoolean("dual_nr", true)) { 60 | initHooks(DualNrSupport) 61 | } 62 | if (Utils.getBoolean("dual_sa", true)) { 63 | initHooks(DualSaSupport) 64 | } 65 | if (Utils.getBoolean("n1_band", true)) { 66 | initHooks(N1BandPhone) 67 | } 68 | if (Utils.getBoolean("n28_band", true)) { 69 | initHooks(N28BandPhone) 70 | } 71 | if (Utils.getBoolean("n5_n8_band", true)) { 72 | initHooks(N5N8BandPhone) 73 | } 74 | if (Utils.getBoolean("smart_call_forward", false)) { 75 | initHooks(SmartCallForwardSupport) 76 | } 77 | if (Utils.getBoolean("disable_crbt", false)) { 78 | initHooks(DisableCrbtSupport) 79 | } 80 | if (Utils.getBoolean("vice_slot_volte", false)) { 81 | initHooks(ViceSlotVolteButton) 82 | } 83 | if (Utils.getBoolean("opt", false)) { 84 | initHooks(OptimizationSupport) 85 | } 86 | if (Utils.getBoolean("dualdata", false)) { 87 | initHooks(DualDataSupport) 88 | // initHooks(DsdaSupport) 89 | } 90 | if (Utils.getBoolean("concurrent", false)) { 91 | initHooks(DualdataConcurrent) 92 | } 93 | if (Utils.getBoolean("redundant", false)) { 94 | initHooks(DualdataRedundant) 95 | } 96 | if (Utils.getBoolean("hiking_city", false)) { 97 | initHooks(HikingCity) 98 | } 99 | if (Utils.getBoolean("dualdata_bands", false)) { 100 | initHooks(BandCondition) 101 | } 102 | if (Utils.getBoolean("fiveg_switch", false)) { 103 | initHooks(com.weverses.modempro.hook.hooks.phone.FiveGSwitch) 104 | } 105 | } 106 | "com.xiaomi.mtb" -> { 107 | if (Utils.getBoolean("mtb_auth", false)) { 108 | initHooks(BypassAuthentication) 109 | } 110 | } 111 | } 112 | } 113 | } 114 | 115 | private fun initHooks(vararg hook: BaseHook) { 116 | hook.forEach { 117 | runCatching { 118 | if (it.isInit) return@forEach 119 | it.init() 120 | it.isInit = true 121 | Log.i("Inited hook: ${it.javaClass.simpleName}") 122 | }.logexIfThrow("Failed init hook: ${it.javaClass.simpleName}") 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/BaseHook.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks 2 | 3 | abstract class BaseHook { 4 | var isInit: Boolean = false 5 | abstract fun init() 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/Check.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Check 5 | 6 | object Check: BaseHook() { 7 | // 因为在模块设置页时无法获得宿主的classloader,只能先hook一下宿主了:) 8 | override fun init() { 9 | // Check.getDefBands() 10 | Check.getDefDuaNR() 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/DSDA.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | import com.weverses.modempro.util.Check.isMTK 6 | 7 | object DSDA : BaseHook() { 8 | override fun init() { 9 | if(!isMTK()) { 10 | hookMethodOfBoolean( 11 | "miui.telephony.TelephonyManagerEx", 12 | "isDsdaSupported", 13 | true, 14 | "framework" 15 | ) 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/DualDataSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Platforms Support: 7 | // sm8450/sm8475/sm7475/sm8550 8 | // Framework/Telephone Services Support: 9 | // xm13 series Only 10 | object DualDataSupport : BaseHook() { 11 | override fun init() { 12 | hookMethodOfBoolean( 13 | "miui.telephony.TelephonyManagerEx", 14 | "isDualDataSupported", 15 | true, 16 | "framework" 17 | ) 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/DualNRSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object DualNRSupport : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isDualNrSupported", 11 | true, 12 | "framework" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/DualSASupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object DualSASupport : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isDualSaSupported", 11 | true, 12 | "framework" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/FiveGSwitch.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object FiveGSwitch : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isHideFiveGAndNetwork", 11 | false, 12 | "framework" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/N1Band.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N1Band : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN1Supported", 11 | true, 12 | "framework" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/N28Band.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N28Band : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN28Supported", 11 | true, 12 | "framework" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/N5N8Band.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N5N8Band : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN5Supported", 11 | true, 12 | "framework" 13 | ) 14 | hookMethodOfBoolean( 15 | "miui.telephony.TelephonyManagerEx", 16 | "isN8Supported", 17 | true, 18 | "framework" 19 | ) 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/android/Optimization.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.android 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Check.getMIUIVersion 5 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 6 | 7 | // Platforms Support: 8 | // sm8450/sm8475/sm7475/sm8550 9 | // Framework/Telephone Services Support: 10 | // xm13 series Only 11 | object Optimization : BaseHook() { 12 | override fun init() { 13 | hookMethodOfBoolean( 14 | "miui.telephony.TelephonyManagerEx", 15 | "isAirportOptimizationSupported", 16 | true, 17 | "framework" 18 | ) 19 | hookMethodOfBoolean( 20 | "miui.telephony.TelephonyManagerEx", 21 | "isSubwayOptimizationSupported", 22 | true, 23 | "framework" 24 | ) 25 | hookMethodOfBoolean( 26 | "miui.telephony.TelephonyManagerEx", 27 | "isHikingOptimizationSupported", 28 | true, 29 | "framework" 30 | ) 31 | if (getMIUIVersion() < 15f){ 32 | hookMethodOfBoolean( 33 | "miui.telephony.TelephonyManagerEx", 34 | "isSpecialNetworkOptimizationSupported", 35 | true, 36 | "framework" 37 | ) 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/mtb/BypassAuthentication.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.mtb 2 | 3 | import com.github.kyuubiran.ezxhelper.ClassUtils 4 | import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook 5 | import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder 6 | import com.weverses.modempro.hook.hooks.BaseHook 7 | import com.weverses.modempro.util.Check.getAndroidVersion 8 | import com.weverses.modempro.util.Check.getMIUIVersion 9 | import com.weverses.modempro.util.Check.isOS2 10 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 11 | import com.weverses.modempro.util.Utils.hookMethodOfLong 12 | import com.weverses.modempro.util.Utils.hookMethodOfString 13 | import de.robv.android.xposed.XposedBridge 14 | 15 | object BypassAuthentication : BaseHook() { 16 | override fun init() { 17 | 18 | // 在HyperOS1上 19 | if (getMIUIVersion() > 14f || getAndroidVersion() > "13"){ 20 | try { 21 | ClassUtils.loadClass("com.xiaomi.mtb.XiaoMiServerPermissionCheck").methodFinder().first { 22 | name == "getClassErrorString" 23 | }.createHook{ 24 | after { 25 | it.result = null 26 | } 27 | } 28 | XposedBridge.log("ModemPro: Hook-mtb getClassErrorString success!") 29 | } catch (e: Throwable) { 30 | XposedBridge.log("ModemPro: Hook-mtb getClassErrorString failed!") 31 | XposedBridge.log(e) 32 | } 33 | hookMethodOfBoolean( 34 | "com.xiaomi.modem.ModemUtils", 35 | "isUserBuild", 36 | false, 37 | "mtb" 38 | ) 39 | hookMethodOfLong( 40 | "com.xiaomi.mtb.XiaoMiServerPermissionCheck", 41 | "updatePermissionClass", 42 | 0L, 43 | "mtb" 44 | ) 45 | } 46 | // 在HyperOS2上 47 | if (isOS2()){ 48 | hookMethodOfLong( 49 | "com.xiaomi.mtb.MtbApp", 50 | "getMiServerPermissionClass", 51 | 0L, 52 | "mtb" 53 | ) 54 | hookMethodOfBoolean( 55 | "com.xiaomi.modem.ModemUtils", 56 | "isFactoryBuild", 57 | true, 58 | "mtb" 59 | ) 60 | } 61 | // 在Android 12上 62 | if (getAndroidVersion() < "13") { 63 | hookMethodOfBoolean( 64 | "com.xiaomi.mtb.MtbUtils", 65 | "isUserBuild", 66 | false, 67 | "mtb" 68 | ) 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/BandCondition.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Platforms Support: 7 | // sm8450/sm8475/sm7475/sm8550 8 | // Framework/Telephone Services Support: 9 | // xm13 series Only 10 | object BandCondition : BaseHook() { 11 | override fun init() { 12 | hookMethodOfBoolean( 13 | "com.android.phone.MiuiPhoneUtils", 14 | "isSuitDualBandCondition", 15 | true, 16 | "phone" 17 | ) 18 | } 19 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/Check.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Check 5 | 6 | object Check: BaseHook() { 7 | // 因为在模块设置页时无法获得宿主的classloader,只能先hook一下宿主了:) 8 | val mDualdata = null 9 | override fun init() { 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DisableCrbtSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Platforms Support: 7 | // sm8450/sm8475/sm7475/sm8550 8 | object DisableCrbtSupport : BaseHook() { 9 | override fun init() { 10 | hookMethodOfBoolean( 11 | "com.android.phone.MiuiPhoneUtils", 12 | "isSupportDisableCrbt", 13 | true, 14 | "phone" 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DsdaSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Check.isMTK 5 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 6 | 7 | object DsdaSupport : BaseHook() { 8 | override fun init() { 9 | if(isMTK()) { 10 | hookMethodOfBoolean( 11 | "com.android.phone.MiuiPhoneUtils", 12 | "isDSDASupported", 13 | true, 14 | "phone" 15 | ) 16 | } else { 17 | hookMethodOfBoolean( 18 | "miui.telephony.TelephonyManagerEx", 19 | "isDsdaSupported", 20 | true, 21 | "phone" 22 | ) 23 | 24 | hookMethodOfBoolean( 25 | "com.android.phone.MiuiPhoneUtils", 26 | "isDeviceDsdaSupportedByQcom", 27 | true, 28 | "phone" 29 | ) 30 | } 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DualData.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Platforms Support: 7 | // sm8450/sm8475/sm7475/sm8550 8 | // Framework/Telephone Services Support: 9 | // xm13 series Only 10 | object DualData : BaseHook() { 11 | override fun init() { 12 | hookMethodOfBoolean( 13 | "miui.telephony.TelephonyManagerEx", 14 | "isDualDataSupported", 15 | true, 16 | "phone" 17 | ) 18 | hookMethodOfBoolean( 19 | "com.android.phone.MiuiPhoneUtils", 20 | "shouldHideIntelligentDualSimButton", 21 | false, 22 | "phone" 23 | ) 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DualNrSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object DualNrSupport : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isDualNrSupported", 11 | true, 12 | "phone" 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DualSaSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object DualSaSupport : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isDualSaSupported", 11 | true, 12 | "phone" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DualdataConcurrent.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass 4 | import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook 5 | import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder 6 | import com.weverses.modempro.hook.hooks.BaseHook 7 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 8 | import com.weverses.modempro.util.Utils.hookMethodOfField 9 | import com.weverses.modempro.util.getPackageNames 10 | import com.weverses.modempro.util.getPackageNames.getAllAppPackageNames 11 | import de.robv.android.xposed.XposedBridge 12 | 13 | // Platforms Support: 14 | // sm8450/sm8475/sm7475/sm8550 15 | // Framework/Telephone Services Support: 16 | // xm13 series Only 17 | object DualdataConcurrent : BaseHook() { 18 | override fun init() { 19 | // 这样应该就是直接使其返回空了吧,也许吧 20 | loadClass("com.android.phone.dsda.MiuiDualDataController") 21 | .methodFinder() 22 | .filterByName("initDualDataConcurrentModeWhiteList") 23 | .first() 24 | .createHook { 25 | before { param -> 26 | null 27 | } 28 | } 29 | loadClass("com.android.phone.dsda.MiuiDualDataController") 30 | .methodFinder() 31 | .filterByName("updateDualDataConcurrentModeAppWhiteList") 32 | .first() 33 | .createHook { 34 | before { param -> 35 | null 36 | } 37 | } 38 | XposedBridge.log("ModemPro: Hook-phone initDualDataConcurrentModeWhiteList success!") 39 | // 我也不知道为什么直接hook return true不可以 40 | /* 41 | hookMethodOfBoolean( 42 | "com.android.phone.dsda.MiuiDualDataController", 43 | "isConcurrentWhiteListApp", 44 | true, 45 | "phone" 46 | ) 47 | hookMethodOfBoolean( 48 | "com.android.phone.dsda.MiuiDualDataController", 49 | "isRedundantWhiteListApp", 50 | false, 51 | "phone" 52 | ) 53 | hookMethodOfField( 54 | "com.android.phone.dsda.MiuiDualDataController", 55 | "processForegroundInfoEvent", 56 | "mConcurrentWhiteListForground", 57 | "true", 58 | "phone" 59 | ) 60 | hookMethodOfField( 61 | "com.android.phone.dsda.MiuiDualDataController", 62 | "processForegroundInfoEvent", 63 | "mRedundantWhiteListForground", 64 | "false", 65 | "phone" 66 | ) 67 | */ 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/DualdataRedundant.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.github.kyuubiran.ezxhelper.ClassUtils 4 | import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook 5 | import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder 6 | import com.weverses.modempro.hook.hooks.BaseHook 7 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 8 | import com.weverses.modempro.util.Utils.hookMethodOfField 9 | import de.robv.android.xposed.XposedBridge 10 | 11 | // Platforms Support: 12 | // sm8450/sm8475/sm7475/sm8550 13 | // Framework/Telephone Services Support: 14 | // xm13 series Only 15 | object DualdataRedundant : BaseHook() { 16 | override fun init() { 17 | // 这样应该就是直接使其返回空了吧,也许吧 18 | ClassUtils.loadClass("com.android.phone.dsda.MiuiDualDataController") 19 | .methodFinder() 20 | .filterByName("initDualDataRedundantModeWhiteList") 21 | .first() 22 | .createHook { 23 | before { param -> 24 | null 25 | } 26 | } 27 | ClassUtils.loadClass("com.android.phone.dsda.MiuiDualDataController") 28 | .methodFinder() 29 | .filterByName("updateDualDataRedundantModeAppWhiteList") 30 | .first() 31 | .createHook { 32 | before { param -> 33 | null 34 | } 35 | } 36 | XposedBridge.log("ModemPro: Hook-phone initDualDataRedundantModeWhiteList success!") 37 | /* 38 | hookMethodOfBoolean( 39 | "com.android.phone.dsda.MiuiDualDataController", 40 | "isConcurrentWhiteListApp", 41 | true, 42 | "phone" 43 | ) 44 | hookMethodOfBoolean( 45 | "com.android.phone.dsda.MiuiDualDataController", 46 | "isRedundantWhiteListApp", 47 | false, 48 | "phone" 49 | ) 50 | hookMethodOfField( 51 | "com.android.phone.dsda.MiuiDualDataController", 52 | "processForegroundInfoEvent", 53 | "mConcurrentWhiteListForground", 54 | "true", 55 | "phone" 56 | ) 57 | hookMethodOfField( 58 | "com.android.phone.dsda.MiuiDualDataController", 59 | "processForegroundInfoEvent", 60 | "mRedundantWhiteListForground", 61 | "false", 62 | "phone" 63 | ) 64 | */ 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/FiveGSwitch.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object FiveGSwitch : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isHideFiveGAndNetwork", 11 | false, 12 | "phone" 13 | ) 14 | hookMethodOfBoolean( 15 | "com.android.phone.utils.FiveGUtils", 16 | "isFiveGInvisableByDefault", 17 | false, 18 | "phone" 19 | ) 20 | hookMethodOfBoolean( 21 | "com.android.phone.FiveGCloudController", 22 | "isFiveGSwitchInVisibleByCloud", 23 | false, 24 | "phone" 25 | ) 26 | hookMethodOfBoolean( 27 | "com.android.phone.FiveGCloudController", 28 | "isFiveGSwitchVisibleByCloud", 29 | true, 30 | "phone" 31 | ) 32 | hookMethodOfBoolean( 33 | "com.android.phone.utils.FiveGUtils", 34 | "isFiveGNetworkForceVisable", 35 | true, 36 | "phone" 37 | ) 38 | hookMethodOfBoolean( 39 | "com.android.phone.FiveGCloudController", 40 | "isFiveGNetWorkInVisible", 41 | false, 42 | "phone" 43 | ) 44 | } 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/HikingCity.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Framework/Telephone Services Support: 7 | // xm13 series Only 8 | object HikingCity : BaseHook() { 9 | override fun init() { 10 | hookMethodOfBoolean( 11 | "com.android.phone.NetworkModeRecognition", 12 | "isCityWhiteList", 13 | true, 14 | "phone" 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/ModemFeature.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.github.kyuubiran.ezxhelper.ClassUtils 4 | import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook 5 | import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder 6 | import com.weverses.modempro.hook.hooks.BaseHook 7 | import com.weverses.modempro.util.Utils 8 | import com.weverses.modempro.util.Utils.hookMethodOfArgs 9 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 10 | import de.robv.android.xposed.XposedBridge 11 | 12 | object ModemFeature : BaseHook() { 13 | override fun init() { 14 | hookMethodOfArgs( 15 | "com.android.phone.FiveGManagerBase", 16 | "getModemFeatureMode", 17 | 0, 18 | "-1", 19 | "mtb" 20 | ) 21 | hookMethodOfBoolean( 22 | "com.android.phone.FiveGManagerBase", 23 | "getModemFeatureMode", 24 | true, 25 | "mtb" 26 | ) 27 | 28 | hookMethodOfArgs( 29 | "com.android.phone.MiuiPhoneUtils", 30 | "isModemFeatureSupported", 31 | 0, 32 | "-1", 33 | "mtb" 34 | ) 35 | hookMethodOfArgs( 36 | "com.android.phone.FiveGManagerBase", 37 | "getModemFeatureFromDb", 38 | 0, 39 | "-1", 40 | "mtb" 41 | ) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/N1BandPhone.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N1BandPhone : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN1Supported", 11 | true, 12 | "phone" 13 | ) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/N28BandPhone.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N28BandPhone : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN28Supported", 11 | true, 12 | "phone" 13 | ) 14 | } 15 | } 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/N5N8BandPhone.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | object N5N8BandPhone : BaseHook() { 7 | override fun init() { 8 | hookMethodOfBoolean( 9 | "miui.telephony.TelephonyManagerEx", 10 | "isN5Supported", 11 | true, 12 | "phone" 13 | ) 14 | hookMethodOfBoolean( 15 | "miui.telephony.TelephonyManagerEx", 16 | "isN8Supported", 17 | true, 18 | "phone" 19 | ) 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/OptimizationSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Check.getMIUIVersion 5 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 6 | import com.weverses.modempro.util.Check.isMTK 7 | 8 | // Platforms Support: 9 | // sm8450/sm8475/sm7475/sm8550 10 | // Framework/Telephone Services Support: 11 | // xm13 series Only 12 | object OptimizationSupport : BaseHook() { 13 | override fun init() { 14 | hookMethodOfBoolean( 15 | "miui.telephony.TelephonyManagerEx", 16 | "isAirportOptimizationSupported", 17 | true, 18 | "phone" 19 | ) 20 | hookMethodOfBoolean( 21 | "miui.telephony.TelephonyManagerEx", 22 | "isSubwayOptimizationSupported", 23 | true, 24 | "phone" 25 | ) 26 | hookMethodOfBoolean( 27 | "miui.telephony.TelephonyManagerEx", 28 | "isHikingOptimizationSupported", 29 | true, 30 | "phone" 31 | ) 32 | 33 | if (getMIUIVersion() < 15f) { 34 | hookMethodOfBoolean( 35 | "com.android.phone.MiuiPhoneUtils", 36 | "isSpecialNetworkOptimizationSupported", 37 | true, 38 | "phone" 39 | ) 40 | if (isMTK()) { 41 | hookMethodOfBoolean( 42 | "com.android.phone.MiuiPhoneUtils", 43 | "isSpecialNetworkOptimizationSupportedMtk", 44 | true, 45 | "phone" 46 | ) 47 | } else { 48 | hookMethodOfBoolean( 49 | "com.android.phone.MiuiPhoneUtils", 50 | "isSpecialNetworkOptimizationSupportedQcom", 51 | true, 52 | "phone" 53 | ) 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/SmartCallForwardSupport.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 5 | 6 | // Platforms Support: 7 | // sm8450/sm8475/sm7475/sm8550 8 | object SmartCallForwardSupport : BaseHook() { 9 | override fun init() { 10 | hookMethodOfBoolean( 11 | "com.android.phone.SmartCallForwardUtils", 12 | "isSupportSmartCallForwardByDevice", 13 | true, 14 | "phone" 15 | ) 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/hook/hooks/phone/ViceSlotVolteButton.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.hook.hooks.phone 2 | 3 | import com.weverses.modempro.hook.hooks.BaseHook 4 | import com.weverses.modempro.util.Utils 5 | import com.weverses.modempro.util.Utils.hookMethodOfBoolean 6 | import de.robv.android.xposed.XposedBridge 7 | 8 | object ViceSlotVolteButton : BaseHook() { 9 | override fun init() { 10 | try { 11 | Utils.exec("settings put global vice_slot_volte_data_enabled 1") 12 | XposedBridge.log("ModemPro: enable ViceSlotVolte success!") 13 | hookMethodOfBoolean( 14 | "com.android.phone.MiuiPhoneUtils", 15 | "shouldHideViceSlotVolteDataButton", 16 | false, 17 | "phone" 18 | ) 19 | } catch (e: Throwable) { 20 | XposedBridge.log("ModemPro: Set settings int failed!") 21 | XposedBridge.log(e) 22 | } 23 | hookMethodOfBoolean( 24 | "com.android.phone.MiuiPhoneUtils", 25 | "shouldHideSmartDualSimButton", 26 | false, 27 | "phone" 28 | ) 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/util/Check.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.util 2 | 3 | import com.weverses.modempro.util.Utils.getDefReturn 4 | import com.weverses.modempro.util.Utils.getMethodDefReturn 5 | import com.weverses.modempro.util.Utils.getPlatform 6 | import com.weverses.modempro.util.Utils.getProp 7 | import de.robv.android.xposed.XposedBridge 8 | import de.robv.android.xposed.XposedHelpers 9 | 10 | object Check { 11 | val DualdataDevices: Array = arrayOf("fuxi","cas","nuwa","ishtar") 12 | 13 | fun isOS2(): Boolean { 14 | return (getProp("ro.build.version.release") == "2") 15 | } 16 | 17 | fun isUnSupportedMIUIVersion(): Boolean { 18 | return (getMIUIVersion() < 13f) 19 | } 20 | 21 | fun isMTK(): Boolean { 22 | return (getProp("Build.BRAND") == "MTK") 23 | } 24 | 25 | fun iskonaPlatform(): Boolean{ 26 | // 感觉除了865平台之外其他平台确实用不到这个功能,那就隐藏起来吧:) 27 | return (getPlatform() == "kona") 28 | } 29 | 30 | fun islahainaPlatform(): Boolean{ 31 | // 感觉除了888平台之外其他平台确实用不到这个功能,那就隐藏起来吧:) 32 | return (getPlatform() == "lahaina") 33 | } 34 | 35 | fun istaroPlatform(): Boolean{ 36 | // 感觉除了8+平台之外其他平台确实用不到这个功能,那就隐藏起来吧:) 37 | return (getPlatform() == "taro") 38 | } 39 | 40 | val framework = "miui.telephony.TelephonyManagerEx" 41 | 42 | fun getDefBands() { 43 | val bandMethods = mapOf( 44 | "N5" to "isN5Supported", 45 | "N8" to "isN8Supported", 46 | "N28" to "isN28Supported" 47 | ) 48 | val bands = StringBuilder() 49 | val supportedBands = mutableListOf() 50 | for ((band, methodName) in bandMethods) { 51 | val isSupported = getDefReturn(framework, methodName) 52 | if (isSupported == "true") { 53 | supportedBands.add(band) 54 | } 55 | } 56 | bands.append(supportedBands.joinToString(",")) 57 | val result = bands.toString() 58 | // 为了实现这个日志输出貌似只能这样写了emm 59 | XposedBridge.log("ModemPro: Def NR Bands Support: $result") 60 | 61 | val isN5Support = supportedBands.contains("N5") 62 | val isN8Support = supportedBands.contains("N8") 63 | val isN28Support = supportedBands.contains("N28") 64 | } 65 | 66 | fun getDefDuaNR(){ 67 | val NR = getDefReturn(framework,"isDualNrSupported") 68 | val SA = getDefReturn(framework,"isDualSaSupported") 69 | val FiveG = StringBuilder() 70 | 71 | if (NR == "true") { 72 | FiveG.append("DualNR,") 73 | } 74 | if (SA == "true") { 75 | FiveG.append("DualSA,") 76 | } 77 | val result = FiveG.trimEnd(',') 78 | 79 | XposedBridge.log("ModemPro: Def 5G Support: $result") 80 | } 81 | fun getMIUIVersion(): Float = when (getProp("ro.miui.ui.version.name")){ 82 | // 为了防止一些早期泄露pre-HyperOS无法识别,故加入V818 83 | "V818" -> 14.9f 84 | "V816" -> 15f 85 | "V140" -> 14f 86 | "V130" -> 13f 87 | "V125" -> 12.5f 88 | "V12" -> 12f 89 | "V11" -> 11f 90 | "V10" -> 10f 91 | else -> 0f 92 | } 93 | 94 | fun getAndroidVersion(): String{ 95 | return (getProp("ro.build.version.release")) 96 | } 97 | 98 | 99 | } -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/util/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.util 2 | 3 | import android.os.Build 4 | import com.weverses.modempro.BuildConfig 5 | import de.robv.android.xposed.XSharedPreferences 6 | import java.io.BufferedReader 7 | import java.io.DataOutputStream 8 | import java.io.IOException 9 | import java.io.InputStreamReader 10 | import com.github.kyuubiran.ezxhelper.ClassUtils.loadClass 11 | import com.github.kyuubiran.ezxhelper.ClassUtils.loadClassOrNull 12 | import com.github.kyuubiran.ezxhelper.HookFactory.`-Static`.createHook 13 | import com.github.kyuubiran.ezxhelper.ObjectHelper.Companion.objectHelper 14 | import com.github.kyuubiran.ezxhelper.finders.MethodFinder.`-Static`.methodFinder 15 | import com.github.kyuubiran.ezxhelper.interfaces.IMethodHookCallback 16 | import de.robv.android.xposed.XC_MethodHook 17 | import de.robv.android.xposed.XposedBridge 18 | import de.robv.android.xposed.XposedHelpers 19 | 20 | object Utils { 21 | fun exec(command: String): String { 22 | var process: Process? = null 23 | var reader: BufferedReader? = null 24 | var `is`: InputStreamReader? = null 25 | var os: DataOutputStream? = null 26 | return try { 27 | process = Runtime.getRuntime().exec("su") 28 | `is` = InputStreamReader(process.inputStream) 29 | reader = BufferedReader(`is`) 30 | os = DataOutputStream(process.outputStream) 31 | os.writeBytes( 32 | command.trimIndent() 33 | ) 34 | os.writeBytes("\nexit\n") 35 | os.flush() 36 | var read: Int 37 | val buffer = CharArray(4096) 38 | val output = StringBuilder() 39 | while (reader.read(buffer).also { read = it } > 0) { 40 | output.append(buffer, 0, read) 41 | } 42 | process.waitFor() 43 | output.toString() 44 | } catch (e: IOException) { 45 | throw RuntimeException(e) 46 | } catch (e: InterruptedException) { 47 | throw RuntimeException(e) 48 | } finally { 49 | try { 50 | os?.close() 51 | `is`?.close() 52 | reader?.close() 53 | process?.destroy() 54 | } catch (e: IOException) { 55 | e.printStackTrace() 56 | } 57 | } 58 | } 59 | 60 | fun exec(commands: Array): String { 61 | val stringBuilder = java.lang.StringBuilder() 62 | for (command in commands) { 63 | stringBuilder.append(exec(command)) 64 | stringBuilder.append("\n") 65 | } 66 | return stringBuilder.toString() 67 | } 68 | 69 | fun getBoolean(key: String, defValue: Boolean): Boolean { 70 | val prefs = XSharedPreferences(BuildConfig.APPLICATION_ID, "config") 71 | if (prefs.hasFileChanged()) { 72 | prefs.reload() 73 | } 74 | return prefs.getBoolean(key, defValue) 75 | } 76 | 77 | fun getProp(mKey: String): String = Class.forName("android.os.SystemProperties").getMethod("get", String::class.java).invoke(Class.forName("android.os.SystemProperties"), mKey).toString() 78 | 79 | fun getPlatform(): String { 80 | return getProp("ro.board.platform") 81 | } 82 | 83 | fun isSupportDevices(mDevice: Array): Boolean { 84 | val device = Build.DEVICE 85 | for (str2 in mDevice) { 86 | if (device == str2) { 87 | return true 88 | } 89 | } 90 | return false 91 | } 92 | 93 | fun checkClassIfExists(className: String): Boolean { 94 | val exist = loadClassOrNull(className) 95 | return exist != null 96 | } 97 | 98 | fun checkMethodIfExists(className: String,methodName: String): Boolean { 99 | val exist = loadClass(className).methodFinder().filterByName(methodName).firstOrNull() 100 | return exist != null 101 | } 102 | 103 | fun getMethodDefReturn(className: String, methodName: String): String { 104 | var originalReturnValue: Any? = null 105 | 106 | loadClass(className).methodFinder() 107 | .filterByName(methodName) 108 | .first() 109 | .createHook { 110 | before(object : IMethodHookCallback { 111 | override fun onMethodHooked(param: XC_MethodHook.MethodHookParam) { 112 | originalReturnValue = param.result 113 | } 114 | }) 115 | } 116 | 117 | // 返回结果 118 | XposedBridge.log("ModemPro: getMethodDefReturn: ${methodName}.return ${originalReturnValue}") 119 | return originalReturnValue?.toString() ?: "null" 120 | } 121 | 122 | fun getDefReturn(className: String, methodName: String): String { 123 | XposedBridge.log("ModemPro: getDefReturn: ${methodName}.return ${getDefReturn(className,methodName)}") 124 | return XposedHelpers.callStaticMethod(loadClass(className),methodName) as String 125 | } 126 | 127 | fun hookMethodOfBoolean(className: String,methodName: String,Result: Boolean,Scope: String) { 128 | try { 129 | loadClass(className).methodFinder().first { 130 | name == methodName 131 | }.createHook{ 132 | after { 133 | it.result = Result 134 | } 135 | } 136 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} success!") 137 | } catch (e: Throwable) { 138 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} failed!") 139 | XposedBridge.log(e) 140 | } 141 | } 142 | 143 | fun hookMethodOfLong(className: String,methodName: String,Result: Long,Scope: String) { 144 | try { 145 | loadClass(className).methodFinder().first { 146 | name == methodName 147 | }.createHook{ 148 | after { 149 | it.result = Result 150 | } 151 | } 152 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} success!") 153 | } catch (e: Throwable) { 154 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} failed!") 155 | XposedBridge.log(e) 156 | } 157 | } 158 | 159 | fun hookMethodOfString(className: String,methodName: String,Result: String,Scope: String) { 160 | try { 161 | loadClass(className).methodFinder().first { 162 | name == methodName 163 | }.createHook{ 164 | after { 165 | it.result = Result 166 | } 167 | } 168 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} success!") 169 | } catch (e: Throwable) { 170 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} failed!") 171 | XposedBridge.log(e) 172 | } 173 | } 174 | 175 | fun hookMethodOfField(className: String,methodName: String,fieldName: String,Result: String,Scope: String) { 176 | try { 177 | loadClass(className).methodFinder().first { 178 | name == methodName 179 | }.createHook{ 180 | before { param -> 181 | param.thisObject.objectHelper().setObject(fieldName,Result) 182 | } 183 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} ${fieldName} success!") 184 | } 185 | } catch (e: Throwable) { 186 | XposedBridge.log("ModemPro: Hook-${Scope} ${className}.${methodName} ${fieldName} failed!") 187 | XposedBridge.log(e) 188 | } 189 | } 190 | 191 | fun hookMethodOfArgs(className: String,methodName: String,Args: Int,Result: String,Scope: String) { 192 | try { 193 | loadClass(className).methodFinder().first { 194 | name == methodName 195 | }.createHook { 196 | before { param -> 197 | param.args[Args] = Result 198 | } 199 | } 200 | XposedBridge.log("ModemPro: Hook-${Scope} ${className} ${methodName} ${Args} success!") 201 | } catch (e: Throwable) { 202 | XposedBridge.log("ModemPro: Hook-${Scope} ${className} ${methodName} ${Args} failed!") 203 | XposedBridge.log(e) 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /app/src/main/java/com/weverses/modempro/util/getPackageNames.kt: -------------------------------------------------------------------------------- 1 | package com.weverses.modempro.util 2 | 3 | import android.content.pm.ApplicationInfo 4 | import android.content.pm.PackageManager 5 | import cn.fkj233.ui.activity.MIUIActivity.Companion.context 6 | 7 | object getPackageNames { 8 | fun getAllAppPackageNames(packageManager: PackageManager): String { 9 | val packages = packageManager.getInstalledPackages(0) 10 | val packageNames = mutableListOf() 11 | 12 | for (packageInfo in packages) { 13 | packageInfo.packageName?.let { 14 | packageNames.add(it) 15 | } 16 | } 17 | return packageNames.joinToString(",") 18 | } 19 | 20 | fun getAllThirdPartyAppPackageNames(packageManager: PackageManager): String { 21 | val packages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA) 22 | val thirdPartyPackageNames = mutableListOf() 23 | 24 | for (packageInfo in packages) { 25 | if (packageInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM == 0) { 26 | val packageName = packageInfo.packageName 27 | if (packageName != null) { 28 | thirdPartyPackageNames.add(packageName) 29 | } 30 | } 31 | } 32 | 33 | return thirdPartyPackageNames.joinToString(",") 34 | } 35 | 36 | /* 37 | private lateinit var appInfoList: MutableList 38 | 39 | /** 40 | * 数据类, 存储应用信息 41 | * 42 | data class MyAppInfo( 43 | val appName: String, 44 | val packageName: String, 45 | val isSystemApp: Boolean 46 | ) 47 | 48 | /** 49 | * 获取应用信息列表 50 | * 51 | * @return [MutableList] 应用信息列表 52 | */ 53 | fun getAppInfoList(): MutableList { 54 | if (::appInfoList.isInitialized) 55 | return appInfoList.apply { 56 | sortBy { it.appName } 57 | }.toMutableList() 58 | appInfoList = mutableListOf() 59 | val pm = context.packageManager 60 | for (appInfo in pm.getInstalledApplications(0)) { 61 | MyAppInfo( 62 | appInfo.loadLabel(pm).toString(), 63 | appInfo.packageName, 64 | appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0 65 | ).also { appInfoList.add(it) } 66 | } 67 | return appInfoList.apply { 68 | sortBy { it.appName } 69 | }.toMutableList() 70 | } 71 | 72 | */ 73 | */ 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/author.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Weverses/ModemPro/74d38bdf067708a9894bfc15c86873a52c7b3c3d/app/src/main/res/drawable/author.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Weverses/ModemPro/74d38bdf067708a9894bfc15c86873a52c7b3c3d/app/src/main/res/drawable/ic_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values-ja/strings.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | Modem Pro 4 | Modem Pro 5 | NRの設定 6 | バンドの設定 7 | MTBの設定 8 | テスト機能の設定 9 | その他 10 | その他の機能の設定 11 | ネットワークシナリオ最適化の設定 12 | デュアルSIMデュアルパス機能の設定 13 | 以下の機能を使用するには、プラットフォームのサポートが必要です (8G2以上、理論上は8G1も使用可能ですが未検証) 14 | オン/オフを切り替え後にシステムを再起動する事で適用されます 15 | 作者について 16 | Weverse 17 | coolapk 18 | 作者の情報 19 | 寄付を歓迎します!! 20 | 寄付 21 | MIUI13-14/HyperOS Modem Feature Pro 22 | 説明 23 | 警告 24 | LSPosedのバージョンが古いか、LSPosedが有効化されていないようです。LSPosedをアップデートするか、有効化をしてからもう一度お試しください。 25 | おっと!これはMTKデバイスなので、いくつかの設定が使用できません。 26 | デュアルNR 27 | メインおよびセカンダリSIMカードで同時に5Gを有効にします (セカンダリSIMカードはNSAのみサポートしています) 28 | デュアルSA 29 | セカンダリSIMカードにSA NRをサポートさせます (テスト) 30 | OK 31 | 再起動 32 | 有効化 33 | 無効化 34 | バイススロットVoLTE 35 | 警告:root権限が必要です!セカンダリSIMでVoLTE通話中にモバイルデータを使用します 36 | ビデオ着信音をオフにする 37 | 「設定→追加設定→開発者向けオプション→セルラーネットワークのデバッグ」で「Turn off profile videos for incoming calls」をオンにする事で通話中のビデオ着信音の表示をオフにします 38 | 他のSIMに転送 39 | 「設定→モバイルネットワーク」で「他のSIMに転送」をオンにする事で、一方のSIMカードが通話ができない場合に他のSIMに転送をします 40 | スマートデュアルSIM 41 | 「設定→モバイルネットワーク→詳細設定」で開く事ができます 42 | スマートデュアルSIM 43 | この機能を有効化する事で対応しているデバイスでデュアルSIMデータトラフィックを同時に使用できます。この機能を有効化するには、「設定→モバイルネットワーク」で「スマートデュアルSIM」をオンにしてください 44 | スマートデュアルSIMのバンド制限を無視 45 | オンにする事でスマートデュアルSIMのバンド制限を無視します 46 | スマートデュアルSIMの4Gの制限を無視 47 | オンにする事でスマートデュアルSIMの4Gの同時接続制限を無視します 48 | 空港の最適化 49 | ハイキングの最適化 50 | 地下鉄の最適化 51 | ネットワークシナリオの最適化 52 | オンにする事で特別な環境のネットワークシナリオの最適化がサポートされます。空港、ハイキング、地下鉄の最適化がサポートされたデバイスで有効化されます 53 | グローバル5GデュアルSIMデータ同時接続 54 | オンにする事でアプリのホワイトリストに関係なく、すべてのアプリで5GデュアルSIMの同時データトラフィックをサポートします。注意:この機能を使用するには、使用をしているデバイスがスマートデュアルSIMをサポートしている事と設定で有効化をしている必要があります。また、この機能は「グローバル5GデュアルSIMデータアシスト」と同時使用はできません 55 | グローバル5GデュアルSIMデータアシスト 56 | オンにする事でアプリのホワイトリストが無視され、すべてのアプリが5GデュアルSIM同時データ通信をサポートするようになります。以前と異なり、これは補助的な使用としてのセカンダリSIMカードの通信になります。注意:この機能を有効化するには、使用しているデバイスが「スマートデュアルSIM」をサポートされている事と設定で有効化をする必要があります。この機能と上記の「グローバル5GデュアルSIM同時接続」を同時に有効化はできません 57 | ハイキング時のシナリオをサポート 58 | オンにする事で都市のホワイトリストが無視され、サポートがされていない都市でハイキング時のネットワークシナリオの最適化が有効化されます。注意:この機能を使用するには、デバイスの設定でネットワークシーンの最適化がオンになっている必要があります 59 | 5Gスイッチ 60 | 一部のモデルのHyperOSは、デフォルトで5Gのオン/オフを切り替える事ができません。この機能をオンにすると5Gの通信を再開させる事ができます 61 | バンドN1 62 | バンドN1をサポートします (NR) 63 | バンドN5/N8 64 | ダイアルインターフェースで *#*#65686633#*#* と入力でN5/N8のバンドをサポートします。"Enabled N5 and N8 Mode" と表示されれば、機能は正常に有効化されています 65 | バンドN28 66 | バンドN28をサポートします (NR) 67 | システムを再起動 68 | 再起動をしますか? 69 | キャンセル 70 | MTBの認証をバイパスする 71 | ダイアルインターフェースで *#*#MODEMTEST#*#* と入力で、MTBの設定を開く事ができるようになります (これは非常に危険な機能である事をご理解ください。この機能を使用する前に必ずモデムを完全にバックアップしてください。この機能によって引き起こされたモデムの損傷については責任を一切負いません) 72 | その他 73 | 完了 74 | デバイスがサポートされていないMIUIバージョンが検出されたため、一部の設定が使用できません! 75 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rCN/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5G设置 4 | 频段设置 5 | MTB 设置 6 | 实验性功能设置 7 | 其他 8 | 其他功能设置 9 | 网络场景优化设置 10 | 双卡双通功能设置 11 | 对于以下功能,需要平台支持方可使用(8G2及以上,理论8G1也可以使用但未经测试) 12 | 开关功能后,需重启手机方能生效 13 | 关于 14 | Weverse 15 | 作者酷安界面 16 | 作者信息 17 | 如果喜欢本模块的话,欢迎进入爱发电给作者投喂! 18 | 爱发电 19 | 一个适用于MIUI13-14及HyperOS的基带增强型模块,可以为您的设备开启一些基带的相关功能 20 | 提示 21 | 警告 22 | 您似乎正在使用过时的 LSPosed 版本或 LSPosed 未激活,请更新 LSPosed 或者激活后再试。 23 | 此设备为MTK机型,5G/频段/MTB设置已自动屏蔽 24 | 双卡5G(SA+NSA) 25 | 开启后,主卡副卡可以同时开启5G网络(副卡仅NSA),受限于NSA网络覆盖,副卡可能并不能稳定5G驻网 26 | 双卡SA(SA+SA) 27 | 开启后,副卡可以开启SA网络 28 | 确定 29 | 重启 30 | 开启 31 | 关闭 32 | 副卡VoLTE通话时可联网 33 | 注意:该功能需要Root权限!开启该功能后,副卡进行通话时会将数据切换到副卡 34 | 关闭视频彩铃 35 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 36 | 智能互转 37 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 38 | 智能双卡切换 39 | 开启该功能后,请在设置->双卡与移动网络->高级设置里打开"智能双卡切换" 40 | 智能双卡 41 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 42 | 无视智能双卡频段限制 43 | 开启后,将无视双卡并发频段限制 44 | 机场优化 45 | 远足优化 46 | 地铁优化 47 | 网络场景优化 48 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 49 | 全局5G双卡数据并发 50 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 51 | 全局5G双卡数据辅助 52 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 53 | 强制支持郊野场景优化 54 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 55 | 解锁N1频段 56 | 开启后可支持N1频段 57 | 解锁N5/N8频段 58 | 开启后可支持N5/N8频段,请开启该功能后在拨号界面中输入 *#*#65686633#*#* ,若提示enable N5 and N8 Mode即解锁成功 59 | 解锁N28频段 60 | 开启后可支持部分机型缺失的N28频段 61 | 重启系统 62 | 确定重启系统? 63 | 取消 64 | 绕过鲁班(MTB)鉴权 65 | (请注意,此项为高度危险性功能,请务必在使用该功能前完整备份基带!若因该功能导致的基带损坏概不负责!)开启后可解锁鲁班(MTB)功能,可在拨号界面输入 *#*#663368378#*#* (ModemTest) 打开鲁班界面 66 | 实验性功能 67 | 运行完成 68 | 检测到不支持的MIUI版本,5G/频段/其他功能设置已自动隐藏 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rHK/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5G設定 4 | 頻段設定 5 | MTB 設定 6 | 實驗性功能設定 7 | 其他 8 | 其他功能設定 9 | 网络场景优化设置 10 | 双卡双通功能设置 11 | 以下功能需要使用小米13系列机型且升级到最新版本方可使用 12 | 开关功能后,需重启手机方能生效 13 | 關於 14 | Weverse 15 | 作者酷安頁面 16 | 作者資訊 17 | 如果喜歡本模組的話,歡迎進入愛發電網站進行贊助! 18 | 愛發電 19 | 一个适用于MIUI14的基带增强型模块,可以为您的设备开启一些基带的相关功能 20 | 提示 21 | 警告 22 | 您似乎正在使用過時的 LSPosed 版本或 LSPosed 未啟用,請更新 LSPosed 或者啟用後重試 23 | 此裝置為MTK機型,5G/頻段/MTB設定已自動隱藏 24 | 雙卡5G(SA+NSA) 25 | 開啟後.主卡副卡可以同時開啟5G網路(副卡僅NSA,受限於NSA網路覆蓋,副卡可能並不能5G駐網) 26 | 雙卡SA(SA+SA) 27 | 開啟後,副卡可以開啟SA網路 28 | 確定 29 | 重啟 30 | 開啟 31 | 關閉 32 | 副卡VoLTE通話時可連網 33 | 注意:該功能需要Root權限! 開啟該功能後,副卡進行通話時會將數據切換到副卡 34 | 关闭视频彩铃 35 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 36 | 智能互转 37 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 38 | 智慧雙卡切換 39 | 開啟該功能後,請在設定->雙卡與行動網路->進階設定裡打開5G智慧切換 40 | 智能双卡 41 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 42 | 无视智能双卡频段限制 43 | 开启后,将无视双卡并发频段限制 44 | 无视智能双卡4G限制 45 | 开启后,将无视双卡并发4G限制 46 | 机场优化 47 | 远足优化 48 | 地铁优化 49 | 网络场景优化 50 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 51 | 全局5G双卡数据并发 52 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 53 | 全局5G双卡数据辅助 54 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 55 | 强制支持郊野场景优化 56 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 57 | 解鎖N1頻段 58 | 開啟後可支援N1頻段 59 | 解鎖N5/N8頻段 60 | 開啟後可支援N5/N8頻段,請開啟該功能後在撥號介面中輸入 *#*#65686633#*#* ,若提示enable N5 and N8 Mode即解鎖成功 61 | 解鎖N28頻段 62 | 開啟後可支援部分機型缺失的N28頻段 63 | 重啟系統 64 | 確定重啟系統? 65 | 取消 66 | 繞過魯班(MTB)鑒權 67 | 【請注意,此項為高度危險性功能,請務必在使用該功能前完整備份基帶! 若因該功能導致的基帶損壞概不負責!】 開啟後可解鎖魯班(MTB)功能,可在撥號介面輸入 *#*#663368378#*#* (ModemTest) 打開魯班介面 68 | 實驗性功能 69 | 執行完成 70 | 檢測到不支持的MIUI版本,5G/頻段/其他功能設定已自動隱藏 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rMO/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5G設定 4 | 頻段設定 5 | MTB 設定 6 | 實驗性功能設定 7 | 其他 8 | 其他功能設定 9 | 网络场景优化设置 10 | 双卡双通功能设置 11 | 以下功能需要使用小米13系列机型且升级到最新版本方可使用 12 | 开关功能后,需重启手机方能生效 13 | 關於 14 | Weverse 15 | 作者酷安頁面 16 | 作者資訊 17 | 如果喜歡本模組的話,歡迎進入愛發電網站進行贊助! 18 | 愛發電 19 | 一个适用于MIUI14的基带增强型模块,可以为您的设备开启一些基带的相关功能 20 | 提示 21 | 警告 22 | 您似乎正在使用過時的 LSPosed 版本或 LSPosed 未啟用,請更新 LSPosed 或者啟用後重試 23 | 此裝置為MTK機型,5G/頻段/MTB設定已自動隱藏 24 | 雙卡5G(SA+NSA) 25 | 開啟後.主卡副卡可以同時開啟5G網路(副卡僅NSA,受限於NSA網路覆蓋,副卡可能並不能5G駐網) 26 | 雙卡SA(SA+SA) 27 | 開啟後,副卡可以開啟SA網路 28 | 確定 29 | 重啟 30 | 開啟 31 | 關閉 32 | 副卡VoLTE通話時可連網 33 | 注意:該功能需要Root權限! 開啟該功能後,副卡進行通話時會將數據切換到副卡 34 | 关闭视频彩铃 35 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 36 | 智能互转 37 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 38 | 智慧雙卡切換 39 | 開啟該功能後,請在設定->雙卡與行動網路->進階設定裡打開5G智慧切換 40 | 智能双卡 41 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 42 | 无视智能双卡频段限制 43 | 开启后,将无视双卡并发频段限制 44 | 无视智能双卡4G限制 45 | 开启后,将无视双卡并发4G限制 46 | 机场优化 47 | 远足优化 48 | 地铁优化 49 | 网络场景优化 50 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 51 | 全局5G双卡数据并发 52 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 53 | 全局5G双卡数据辅助 54 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 55 | 强制支持郊野场景优化 56 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 57 | 解鎖N1頻段 58 | 開啟後可支援N1頻段 59 | 解鎖N5/N8頻段 60 | 開啟後可支援N5/N8頻段,請開啟該功能後在撥號介面中輸入 *#*#65686633#*#* ,若提示enable N5 and N8 Mode即解鎖成功 61 | 解鎖N28頻段 62 | 開啟後可支援部分機型缺失的N28頻段 63 | 重啟系統 64 | 確定重啟系統? 65 | 取消 66 | 繞過魯班(MTB)鑒權 67 | 【請注意,此項為高度危險性功能,請務必在使用該功能前完整備份基帶! 若因該功能導致的基帶損壞概不負責!】 開啟後可解鎖魯班(MTB)功能,可在撥號介面輸入 *#*#663368378#*#* (ModemTest) 打開魯班介面 68 | 實驗性功能 69 | 執行完成 70 | 檢測到不支持的MIUI版本,5G/頻段/其他功能設定已自動隱藏 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rSG/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5G設定 4 | 頻段設定 5 | MTB 設定 6 | 實驗性功能設定 7 | 其他 8 | 其他功能設定 9 | 网络场景优化设置 10 | 双卡双通功能设置 11 | 以下功能需要使用小米13系列机型且升级到最新版本方可使用 12 | 开关功能后,需重启手机方能生效 13 | 關於 14 | Weverse 15 | 作者酷安頁面 16 | 作者資訊 17 | 如果喜歡本模組的話,歡迎進入愛發電網站進行贊助! 18 | 愛發電 19 | 一个适用于MIUI14的基带增强型模块,可以为您的设备开启一些基带的相关功能 20 | 提示 21 | 警告 22 | 您似乎正在使用過時的 LSPosed 版本或 LSPosed 未啟用,請更新 LSPosed 或者啟用後重試 23 | 此裝置為MTK機型,5G/頻段/MTB設定已自動隱藏 24 | 雙卡5G(SA+NSA) 25 | 開啟後.主卡副卡可以同時開啟5G網路(副卡僅NSA,受限於NSA網路覆蓋,副卡可能並不能5G駐網) 26 | 雙卡SA(SA+SA) 27 | 開啟後,副卡可以開啟SA網路 28 | 確定 29 | 重啟 30 | 開啟 31 | 關閉 32 | 副卡VoLTE通話時可連網 33 | 注意:該功能需要Root權限! 開啟該功能後,副卡進行通話時會將數據切換到副卡 34 | 关闭视频彩铃 35 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 36 | 智能互转 37 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 38 | 智慧雙卡切換 39 | 開啟該功能後,請在設定->雙卡與行動網路->進階設定裡打開5G智慧切換 40 | 智能双卡 41 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 42 | 无视智能双卡频段限制 43 | 开启后,将无视双卡并发频段限制 44 | 无视智能双卡4G限制 45 | 开启后,将无视双卡并发4G限制 46 | 机场优化 47 | 远足优化 48 | 地铁优化 49 | 网络场景优化 50 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 51 | 全局5G双卡数据并发 52 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 53 | 全局5G双卡数据辅助 54 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 55 | 强制支持郊野场景优化 56 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 57 | 解鎖N1頻段 58 | 開啟後可支援N1頻段 59 | 解鎖N5/N8頻段 60 | 開啟後可支援N5/N8頻段,請開啟該功能後在撥號介面中輸入 *#*#65686633#*#* ,若提示enable N5 and N8 Mode即解鎖成功 61 | 解鎖N28頻段 62 | 開啟後可支援部分機型缺失的N28頻段 63 | 重啟系統 64 | 確定重啟系統? 65 | 取消 66 | 繞過魯班(MTB)鑒權 67 | 【請注意,此項為高度危險性功能,請務必在使用該功能前完整備份基帶! 若因該功能導致的基帶損壞概不負責!】 開啟後可解鎖魯班(MTB)功能,可在撥號介面輸入 *#*#663368378#*#* (ModemTest) 打開魯班介面 68 | 實驗性功能 69 | 執行完成 70 | 檢測到不支持的MIUI版本,5G/頻段/其他功能設定已自動隱藏 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh-rTW/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5G設定 4 | 頻段設定 5 | MTB 設定 6 | 實驗性功能設定 7 | 其他 8 | 其他功能設定 9 | 网络场景优化设置 10 | 双卡双通功能设置 11 | 以下功能需要使用小米13系列机型且升级到最新版本方可使用 12 | 开关功能后,需重启手机方能生效 13 | 關於 14 | Weverse 15 | 作者酷安頁面 16 | 作者資訊 17 | 如果喜歡本模組的話,歡迎進入愛發電網站進行贊助! 18 | 愛發電 19 | 一个适用于MIUI14的基带增强型模块,可以为您的设备开启一些基带的相关功能 20 | 提示 21 | 警告 22 | 您似乎正在使用過時的 LSPosed 版本或 LSPosed 未啟用,請更新 LSPosed 或者啟用後重試 23 | 此裝置為MTK機型,5G/頻段/MTB設定已自動隱藏 24 | 雙卡5G(SA+NSA) 25 | 開啟後.主卡副卡可以同時開啟5G網路(副卡僅NSA,受限於NSA網路覆蓋,副卡可能並不能5G駐網) 26 | 雙卡SA(SA+SA) 27 | 開啟後,副卡可以開啟SA網路 28 | 確定 29 | 重啟 30 | 開啟 31 | 關閉 32 | 副卡VoLTE通話時可連網 33 | 注意:該功能需要Root權限! 開啟該功能後,副卡進行通話時會將數據切換到副卡 34 | 关闭视频彩铃 35 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 36 | 智能互转 37 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 38 | 智慧雙卡切換 39 | 開啟該功能後,請在設定->雙卡與行動網路->進階設定裡打開5G智慧切換 40 | 智能双卡 41 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 42 | 无视智能双卡频段限制 43 | 开启后,将无视双卡并发频段限制 44 | 无视智能双卡4G限制 45 | 开启后,将无视双卡并发4G限制 46 | 机场优化 47 | 远足优化 48 | 地铁优化 49 | 网络场景优化 50 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 51 | 全局5G双卡数据并发 52 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 53 | 全局5G双卡数据辅助 54 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 55 | 强制支持郊野场景优化 56 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 57 | 解鎖N1頻段 58 | 開啟後可支援N1頻段 59 | 解鎖N5/N8頻段 60 | 開啟後可支援N5/N8頻段,請開啟該功能後在撥號介面中輸入 *#*#65686633#*#* ,若提示enable N5 and N8 Mode即解鎖成功 61 | 解鎖N28頻段 62 | 開啟後可支援部分機型缺失的N28頻段 63 | 重啟系統 64 | 確定重啟系統? 65 | 取消 66 | 繞過魯班(MTB)鑒權 67 | 【請注意,此項為高度危險性功能,請務必在使用該功能前完整備份基帶! 若因該功能導致的基帶損壞概不負責!】 開啟後可解鎖魯班(MTB)功能,可在撥號介面輸入 *#*#663368378#*#* (ModemTest) 打開魯班介面 68 | 實驗性功能 69 | 執行完成 70 | 檢測到不支持的MIUI版本,5G/頻段/其他功能設定已自動隱藏 71 | 72 | -------------------------------------------------------------------------------- /app/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | android 5 | com.android.phone 6 | com.xiaomi.mtb 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF000000 4 | #FFFFFFFF 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Modem Pro 4 | Modem Pro 5 | NR Settings 6 | Band Settings 7 | MTB Settings 8 | Test feature Settings 9 | Other 10 | Other feature Settings 11 | 网络场景优化设置 12 | 双卡双通功能设置 13 | 对于以下功能,需要平台支持方可使用(8G2及以上,理论8G1也可以使用但未经测试) 14 | 开关功能后,需重启手机方能生效 15 | About 16 | Weverse 17 | coolapk 18 | Author Informations 19 | Donations WELCOME!! 20 | Donations 21 | MIUI13-14/HyperOS Modem Feature Pro 22 | Tips 23 | Warning 24 | You seem to be using an outdated version of LSPosed or LSPosed is not active, please update LSPosed or activate it and try again. 25 | Oops!This is a MTK-DEVICE,some settings are unavailable 26 | Dual NR 27 | Main and secondary SIM-card enable 5G at the same time(the secondary SIM-card only support NSA) 28 | Dual SA 29 | the secondary SIM-card will support SA NR(test) 30 | OK 31 | Reboot 32 | Enable 33 | Disable 34 | Vice slot volte 35 | Warning:NEED ROOT!Use mobile data during VoLTE calls on the secondary SIM 36 | 关闭视频彩铃 37 | 在设置->更多设置->开发者选项里打开"关闭视频彩铃"后,关闭呼叫过程中的视频彩铃显示功能,仅供测试使用 38 | 智能互转 39 | 在设置->双卡与移动网络里打开"智能互转"后,一张SIM卡来电无法呼入时,呼叫转移至另一张SIM卡 40 | Smart Dual Sim 41 | Settings->SIM cards & mobile networks->Advanced settings 42 | 智能双卡 43 | 开启后,在支持的设备上双卡数据流量可以并发使用.开启该功能后,请在设置->双卡与移动网络里打开"智能双卡" 44 | 无视智能双卡频段限制 45 | 开启后,将无视双卡并发频段限制 46 | 无视智能双卡4G限制 47 | 开启后,将无视双卡并发4G限制 48 | 机场优化 49 | 远足优化 50 | 地铁优化 51 | 网络场景优化 52 | 开启后,将支持特殊网络场景优化,在支持的设备上可以开启机场/郊野/地铁优化 53 | 全局5G双卡数据并发 54 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与下面的“全局5G双卡数据辅助”不能同时开启 55 | 全局5G双卡数据辅助 56 | 开启后,将无视APP白名单,全部APP都将支持5G双卡并发数据流量,与上一个对比区别是这个是副卡的数据流量仅作为辅助使用.注意: 您的设备必须支持并且在设置里开启了智能双卡后才能生效,且这个功能与上面的“全局5G双卡数据并发”不能同时开启 57 | 强制支持郊野场景优化 58 | 开启后,将无视城市白名单,在不支持的城市中开启郊野网络场景优化.注意: 您的设备必须在设置里开启网络场景优化后才能生效 59 | 5G 开关 60 | 对于部分HyperOS机型,默认无法在系统设置中开关5G。开启该功能后即可恢复5G开关 61 | N1 Band 62 | Support N1 Band(NR) 63 | N5/N8 Band 64 | Enter *#*#65686633#*#* on the dial interface to Support N5/N8 Band.If it shows "enable N5 and N8 Mode",the feature will enabled successfully. 65 | N28 Band 66 | Support N28 Band(NR) 67 | Reboot system 68 | Are you sure to reboot? 69 | Cancel 70 | Bypass MTB authentication 71 | (Please note that this is a highly dangerous feature, be sure to fully back up the modem before using this function! We are not responsible for modem damage caused by this function)Enter *#*#MODEMTEST#*#* on the dial interface to open the MTB Settings 72 | More 73 | Finished 74 | Detected that unsupported miui version of your device,some settings are unavailable! 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") version "8.0.0" apply false 3 | id("com.android.library") version "8.0.0" apply false 4 | id("org.jetbrains.kotlin.android") version "1.9.0" apply false 5 | } 6 | 7 | tasks.register("clean").configure { 8 | delete(rootProject.buildDir) 9 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | android.defaults.buildfeatures.buildconfig=true 23 | android.nonFinalResIds=false 24 | android.enableR8.fullMode=false 25 | android.nonTransitiveRClass=false 26 | android.suppressUnsupportedCompileSdk=34 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Weverses/ModemPro/74d38bdf067708a9894bfc15c86873a52c7b3c3d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Mar 14 19:40:19 CST 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | google() 5 | mavenCentral() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | maven("https://api.xposed.info/") 14 | } 15 | } 16 | 17 | include(":app") 18 | include(":blockmiui") 19 | rootProject.name = "ModemPro" -------------------------------------------------------------------------------- /version.txt: -------------------------------------------------------------------------------- 1 | 2.2.0 --------------------------------------------------------------------------------