• Stars
    star
    262
  • Rank 156,136 (Top 4 %)
  • Language
    Java
  • License
    MIT License
  • Created over 3 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

HiddenApiRefinePlugin

A Gradle plugin that improves the experience when developing Android apps, especially system tools, that use hidden APIs.

Background

When developing system tools, it's inevitable to use hidden APIs. There are two ways to use hidden APIs, the reflection way and the linking way. For some types of system tools, a large amount of hidden APIs is required, using the reflection way is too inconvenient. So the linking way is commonly used in those projects.

In short, the linking way is to create Java-only modules with stub classes and then compileOnly them in the main Android modules. This is the same as what Android SDK's android.jar does.

However, the linking way, or "the stub way", have some problems:

  1. "Bridge classes" is required if only some members of the class are hidden.
  2. Kotlin will try to link public classes from the stub module, implementation a second Java-only which compileOnly the stub module can workaround the problem.
  3. Interface implementation will be removed by R8 if the stub module is not compileOnly directly from the main module, however doing this will bring back problem 2.

This plugin is to solve these problems.

What do this plugin do

This plugin uses the Transform API of the Android Gradle Plugin to create a transform that modifies class names, the names are user specified by annotation @RefineAs. So that all the problems will be gone and the stub module does not need to be a Java-only module.

The idea and the implementation is from @Kr328.

Usage

gradle-plugin annotation-processor annotation runtime

Replace all the <version> below with the version shows here.

Create "hidden-api" module

  1. Create a new Android library module

  2. Add annotation dependency

    dependencies {
        annotationProcessor 'dev.rikka.tools.refine:annotation-processor:<version>'
        compileOnly 'dev.rikka.tools.refine:annotation:<version>'
    }
  3. Add the hidden classes

    Here, we use a hidden PackageManager API as the example.

    package android.content.pm;
    
    import dev.rikka.tools.refine.RefineAs;
    
    @RefineAs(PackageManager.class)
    public class PackageManagerHidden {
        public interface OnPermissionsChangedListener {
            void onPermissionsChanged(int uid);
        }
    
        public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
            throw new RuntimeException("Stub!");
        }
        public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
            throw new RuntimeException("Stub!");
        }
    }

    This line @RefineAs(PackageManager.class) will let the plugin renames android.app.PackageManagerHidden/android.app.PackageManagerHidden.OnPermissionsChangedListener to android.app.PackageManager/android.app.PackageManager.OnPermissionsChangedListener.

Use hidden API

  1. Apply this plugin in the final Android application module

    plugins {
        id('dev.rikka.tools.refine') version '<version>'
    }

    If your project includes mulitple modules, you need to apply this plugin to all the module that uses hidden APIs.

    There is a convenient way to do this, add this to your root build.gradle:

    subprojects {
        plugins.withId("com.android.base") {
            plugins.apply('dev.rikka.tools.refine')
        }
    }
  2. Import "hidden-api" module with compileOnly

    dependencies {
        compileOnly project(':hidden-api')
    }
  3. Import the "Refine" class (Optional, if you don't need the "unsafeCast" method)

    dependencies {
        implementation("dev.rikka.tools.refine:runtime:<version>")
    }
  4. Use the hidden API

    Refine.<PackageManagerHidden>unsafeCast(context.getPackageManager())
                 .addOnPermissionsChangeListener(new PackageManagerHidden.OnPermissionsChangedListener() {
                     @Override
                     public void onPermissionsChanged(int uid) {
                         // do staff
                     }
                 });

    After R8, this "cast" will be "removed" or "inlined". This line will be identical to a normal method call.

More Repositories

1

Shizuku

Using system APIs directly with adb/root privileges from normal apps through a Java process started with app_process.
Kotlin
9,849
star
2

Riru

Inject into zygote process
C++
4,875
star
3

Sui

Modern super user interface implementation on Android.
Java
1,829
star
4

StorageRedirect-assets

Assets (rules, apks etc) for Storage Redirect app.
Python
667
star
5

WADB

A simple switch for adb (Android Debug Bridge) over network.
Kotlin
548
star
6

Riru-LocationReportEnabler

A Riru module. Enable location report by hook system_property_get.
C++
449
star
7

Shizuku-API

The API and the developer guide for Shizuku and Sui.
Java
403
star
8

App-Ops-issue-tracker

Issue tracker for https://play.google.com/store/apps/details?id=rikka.appops
303
star
9

RikkaX

Rikka's Android libraries.
Java
268
star
10

FCM-for-Mojo

Firebase Cloud Messaging for Mojo-Webqq.
Java
209
star
11

Riru-ModuleTemplate

Module template of Riru.
Shell
146
star
12

SaveCopy

Simple Android app, handle ACTION_VIEW, ACTION_SEND, ACTION_SEND_MULTIPLE, save a copy of the file. For bad apps which only allow users to open files.
Java
132
star
13

FontProvider

Provide NotoCJK (and other) fonts to other app.
Java
105
star
14

websites

Websites for Rikka apps.
Vue
71
star
15

MaterialThemeBuilder

A gradle plugin that generates Material Design 3 theme for Android projects.
Java
54
star
16

FCM-for-Mojo-Server

Server for FCM-for-Mojo
JavaScript
33
star
17

magisk-custom-sepolicy-installer

(Replaced by official solution from Magisk) Installer template for custom Magisk with "sepolicy_custom" support.
Shell
29
star
18

RikkaApps.github.io.backup

CSS
28
star
19

AutoResConfig

A gradle plugin generates resConfig & languages array from project res folder.
Java
27
star
20

Riru-AppConfig

A Riru module. Per-app system property, config (locale, etc.) modification.
10
star
21

TakoStats

Issue tracker & localization for TakoStats.
9
star
22

RikkaApps.github.io

8
star
23

AppOps-Localization

Localization files for AppOps.
4
star