hansalemaos
cyandroemu
Cython

Android Automation Framework for Python on emulators (BlissOs, BlueStacks, LDPlayer, Memu, Mumu, Android Studio ...) and rooted devices WITHOUT ADB!

Last updated Jun 26, 2026
154
Stars
10
Forks
1
Issues
0
Stars/day
Attention Score
44
Language breakdown
No language data available.
Files click to expand
README

📱 CyAndroEmu: Advanced Android Automation Library


Logo

Python / Cython Automation for Android Emulators

Android automations without ADB - directly on emulators

About The Project

CyAndroEmu is a powerful Python library designed for advanced Android automation. For performance reasons, it’s primarily written in C++ and Cython (Line count - C++: 20229 lines / Python: 2960 lines / Cython: 9397 lines), providing multiple backends for interacting with UI elements, handling input events, and efficiently extracting screen data.

Unlike any other Android automation library, CyAndroEmu is designed to run directly and independently on the emulator or rooted device without relying on ADB. This architecture offers significant performance and reliability advantages.


🚀 Why Choose CyAndroEmu?

Key Advantages:

  • No Broken Connections:
Since it operates independently of ADB, you’ll never face issues with unstable or dropped connections.
  • Blazing Fast Automation:
No need for slow ADB screenshot transmissions—screen data is processed directly on the device.
  • Unlimited Device Scalability:
Run as many emulators as your hardware can handle without hitting ADB’s device limits.
  • Natural Mouse Movements:
Supports smooth, human-like mouse movements, making it perfect for bypassing CAPTCHA and anti-bot detection systems.
  • Fingerprint Avoidance:
Eliminate the risk of device fingerprinting. Curious about how easy it is to fingerprint your device? 👉 Check it here
  • Direct Botting Mode with Magisk/KernelSU:
With Magisk or KernelSU, you can start your device and go straight into botting mode—no manual intervention needed.
  • Easy Device-Wide Proxying:
Effortlessly proxy all network traffic using tools like Proxifier or SocksDroid for enhanced privacy and IP rotation.

Additional Highlights:

  • Low-Level Performance:
Thanks to its C++ core, CyAndroEmu achieves unparalleled speed and efficiency, even in resource-intensive environments.
  • Multi-Backend Support:
Choose from various parsers and input methods tailored to different Android environments (real devices, emulators, custom ROMs).
  • Seamless Emulator Integration:
Designed to work flawlessly with popular emulators like BlissOS, BlueStacks, VMware, and more.
  • Root-Friendly:
Full support for rooted devices, enabling deep system-level automation capabilities.
  • Magisk / KernelSU Plugins:
Start your Python automation automatically when the emulator or device boots—no human interaction needed.

Getting Started

Installation

1. Download and install your favorite Android emulator, and ensure it has root access. CyAndroEmu should also work on any rooted smartphone (not tested yet). A non-root version is available here. CyAndroEmu has been tested with the following: * BlueStacks 5 * BlissOs 14, 15, 16 Go (on ProxMox, Virtual Box - Windows and VMWare - Windows) * LDPlayer * MeMuPlay * MuMuPlayer * GenyMotion * Nox Player * Android Studio - Magisk Patched PlayStore API 30 - Android 11

Although neither Magisk nor KernelSU is required, using them can significantly simplify tasks such as running Python scripts at Android startup and automatically adding the Termux folder to the PATH when accessing the ADB shell . They also assist in hiding root access and automating actions - writing your own Plugins is really simple. Here are some of my tutorials in Portuguese/English that teach you how to install them:

| How to install Python on an emulator | | |-----------|-----------| | Video | Video | | Video | Video | | Video | Video | | Video | Video | | Video | Video |


2. Install Termux and TermuxBoot - optional


3. Use the following command to install the required packages (Python, Pandas, NumPy and some other stuff): * Open a ADB shell, and Termux on your emulator and copy and paste this command to the ADB shell to save some typing: * necessary packages:

input text 'yes | pkg up;pkg install -y openssh;pkg install -y git;pkg install -y openssl;pkg install -y python;pkg install -y python-numpy;pkg install -y python-pip;pkg install -y clang;pkg install -y cmake;pkg install -y coreutils;pkg install -y termux-tools;pkg install -y root-repo;pkg install -y cpulimit;pkg install -y tur-repo;pkg install -y python-pandas;pkg install -y tesseract;pkg install -y imagemagick; pkg install -y imagemagick-static;yes | python -m pip install ptpython;yes | python -m pip install cyandroemu;yes | python -m pip install regex;yes | python -m pip install ptpython;yes | python -m pip install setuptools;yes | python -m pip install Cython;yes | python -m pip install requests';input keyevent KEYCODEENTER;input keyevent KEYCODEENTER

* recommended packages:

input text 'yes | pkg up;yes | pkg install -y openssh;yes | pkg install -y ripgrep;yes | pkg rei libexpat;pkg install -y git;pkg install -y openssl;pkg install -y python;pkg install -y cloneit;pkg install -y python-lxml;pkg install -y python-numpy;pkg install -y python-pillow;pkg install -y python-pip;pkg install -y python-scipy;pkg install -y vim-python;pkg install -y clang;pkg install -y cmake;pkg install -y coreutils;pkg install -y termux-exec;pkg install -y termux-tools;pkg install -y root-repo;pkg install -y matplotlib;pkg install -y cpulimit;pkg install -y tur-repo;pkg install -y python-pandas;pkg install -y tmux;pkg install -y opencv-python;pkg install -y boost;pkg install -y boost-headers;pkg install -y boost-static;pkg install -y tesseract; pkg install -y tor; pkg install -y torsocks; pkg install -y fzf; pkg install -y imagemagick; pkg install -y imagemagick-static;pkg install -y python-scikit-image; pkg install -y python-polars; pkg install -y nodejs-20; pkg install -y gcc-14; pkg install -y ffmpeg7;yes | python -m pip install ptpython;yes | python -m pip install cyandroemu;yes | python -m pip install regex;yes | python -m pip install ptpython;yes | python -m pip install setuptools;yes | python -m pip install Cython;yes | python -m pip install requests';input keyevent KEYCODEENTER;input keyevent KEYCODEENTER

4. Accessing Python from the ADB shell. Choose one of the 3 solutions: 1. Recommended: Install the Magisk/KernelSU plugin to automatically add the Termux bin folder to the PATH 2. Add export PATH="$PATH:/data/data/com.termux/files/usr/bin" to /system/etc/mkshrc (don't forget to set the correct owner/group ... afterwards)

3. Manually type export PATH="$PATH:/data/data/com.termux/files/usr/bin" each time you enter the ADB su shell.



Writing Python scripts

Cyandroemu will be compiled the first time you import it! Since this process is very CPU- and memory-intensive, I recommend setting the memory to 8 GB of RAM. Later on, you can reduce it. The SO files can be copied to other instances of your chosen emulator, but be careful: the CPU must be the same, as the C++ files are compiled with the flags -march=native and -mtune=native to ensure the highest possible performance."

Cyandroemu is primarily written in C++ (6 out of 7 parsers, modified sendevent, etc.) and Cython (1 parser and the Python interface), but all automation is handled using the Python class TermuxAutomation.


The Constructor

May Look Intimidating, but It’s Easy to Understand

TermuxAutomation:
    parsers: dict,
    parser_timeout: int = 30,
    addinputtap: bool = True,
    addsendeventmouse_click: bool = True,
    addsendeventtap: bool = True,
    addmouseaction: bool = True,
    mouse_device: str = "/dev/input/event4",
    touch_device: str = "/dev/input/event5",
    keyboard_device: str = "/dev/input/event1",
    touchdevicemax: int = 32767,
    mousedevicemax: int = 65535,
    inputcmdtap: str = "/system/bin/input tap",
    inputcmdtext: str = "/system/bin/input text",
    sendevent_path: str = "/system/bin/sendevent",
    screen_height: int = 768,
    screen_width: int = 1024,
    sh_exe: str = "/bin/sh",
    su_exe: str = "su",
    uiautomatordumppath: str = "/sdcard/window_dump.xml",
    uiautomatorcpulimit: int = 5,
    systembinpath: str = "/system/bin/",
    path_screencap: str = "screencap",
    pathexetesseract: str = "/data/data/com.termux/files/usr/bin/tesseract",
    pathexeimagemagick: str = "/data/data/com.termux/files/usr/bin/magick",
    tesseract_args: str = '"-l por+eng --oem 3"',
    imagemagick_args: object = None,
    tesseractpathoutpic: str = "/sdcard/screenshot.ppm",
    uiautomator2downloadlink1: str = "https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomator-test.apk",
    uiautomator2downloadlink2: str = "https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomator.apk",
    uiautomator2savepath1: str = "/sdcard/app-uiautomator-test.apk",
    uiautomator2savepath2: str = "/sdcard/app-uiautomator.apk",
    lcpdequesize: int = 40960,
    lcpprintstdout: bool = False,
    lcpprintstderr: bool = False,
    kwargs: object = None,
    adbkeyboardlink="https://github.com/hansalemaos/ADBKeyBoard/raw/refs/heads/master/ADBKeyboard.apk",
    adbkeyboardsave_path="/sdcard/ADBKeyboard.apk",
    validadbkeyboards=(
        "com.android.adbkeyboard/.AdbIME",
        "com.github.uiautomator/.AdbKeyboard",
    ),

Each constructor argument explained


parsers: dict

The heart of the library, containing all the C++ applications required to run the automation. To obtain the dictionary, use the following command. The first time you run it, it will take about 5 minutes as the C++ files will be downloaded and compiled using GCC.

parsers = TermuxAutomation.loadparsersordownloadand_compile("g++")

parser_timeout: int = 30

The timeout (in seconds) for subprocess.run.


addinputtap: bool = True

Wether to add the option to input tap any elment.


addsendeventmouse_click: bool = True

Whether to add the option to perform mouse clicks on any element using sendevent.


addsendeventtap: bool = True

Whether to add the option to tap any element using sendevent.


addmouseaction: bool = True

Whether to add the option to perform mouse actions on elements (e.g., move to, right-click, left-click, middle-click, etc.) using a modified version of sendevent.


mouse_device: str = "/dev/input/event4"

touch_device: str = "/dev/input/event5"

keyboard_device: str = "/dev/input/event1"

touchdevicemax: int = 32767

mousedevicemax: int = 65535

The mouse/keyboard/touch devices and their corresponding device max can be identified using

getevent -lp
or by using the static method findsuitabledevicesforinput_events:

dfdevices = TermuxAutomation.findsuitabledevicesforinputevents() # returns a pandas DataFrame

inputcmdtap: str = "/system/bin/input tap"

inputcmdtext: str = "/system/bin/input text"

sendevent_path: str = "/system/bin/sendevent"

These are the standard input commands. In most cases, there’s no need to modify them.


screen_height: int = 768

screen_width: int = 1024

Screen height and screen width, can be identified using

wm size

or by using the static method getresolutionof_screen

screenwidth, screenheight = TermuxAutomation.getresolutionof_screen()
[!CAUTION]
**MAKE SURE TO PROVIDE THE CORRECT VALUES HERE AND DO NOT ROTATE THE SCREEN DURING AUTOMATION!
Many parsers rely on this information to function correctly.**


sh_exe: str = "/bin/sh"

The path to the shell executable, in most cases, there’s no need to modify it.


su_exe: str = "su"

The command used to enter su (superuser) mode. In most cases, there’s no need to modify it.


uiautomatordumppath: str = "/sdcard/window_dump.xml"

Dump path for uiautomator. In most cases, there’s no need to modify it.


uiautomatorcpulimit: int = 5

The CPU usage limit for the UIAutomator + cpulimit backend.


systembinpath: str = "/system/bin/"

The path where system executables are stored. In most cases, there’s no need to modify it.


path_screencap: str = "screencap"

The command used for taking screenshots. In most cases, there’s no need to modify it.


pathexetesseract: str = "/data/data/com.termux/files/usr/bin/tesseract"

The path to the Tesseract executable. In most cases, there’s no need to modify it.


pathexeimagemagick: str = "/data/data/com.termux/files/usr/bin/magick"

The path to the ImageMagick executable. Used for tesseract preprocessing. In most cases, there’s no need to modify it.


tesseract_args: str = '"-l por+eng --oem 3"'

Default Tesseract arguments. The default languages are Portuguese (por) and English (eng), with fully automatic page segmentation but no OSD (default). Use tesseract --help-extra to view all available options. Words are grouped using pandas

**Note: Be aware that changing the output format may cause the parser to crash, as it requires the output to be in hOCR format.**


imagemagick_args: object = None

Pass None if you don’t want to preprocess the screenshot before passing it to Tesseract. If you choose to preprocess, you can provide ImageMagick command-line arguments to adjust the image (e.g., converting to grayscale, increasing contrast) to improve OCR accuracy.


tesseractpathoutpic: str = "/sdcard/screenshot.ppm"

The C++ Tesseract parser captures a screenshot using screencap, converts the image to a PPM format, and saves the converted output to disk before invoking Tesseract. In most cases, there’s no need to modify this path.


uiautomator2downloadlink1: str = "https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomator-test.apk"

uiautomator2downloadlink2: str = "https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomator.apk"

Backups APKs from the Uiautomator2 project.

You can also use my modified version which shows all hidden elements (good for web scraping)

https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomator-testwithhidden_elements.apk

https://github.com/hansalemaos/uiautomator2tocsv/raw/refs/heads/main/app-uiautomatorwithhidden_elements.apk


uiautomator2savepath1: str = "/sdcard/app-uiautomator-test.apk"

uiautomator2savepath2: str = "/sdcard/app-uiautomator.apk"

Download path for the APKs from the Uiautomator2 project. In most cases, there’s no need to modify them.


lcpdequesize: int = 40960

The ring buffer size of the C++ vector used by the Logcat Parser backend. In most cases, there’s no need to modify it.


lcpprintstdout: bool = False

lcpprintstderr: bool = False

Debug print options for the Logcat Parser backend. These should only be enabled if you encounter issues with the Logcat Parser backend.


kwargs: object = None

kwargs for subprocess.run In most cases, there’s no need to modify it.


adbkeyboardlink: str = "https://github.com/hansalemaos/ADBKeyBoard/raw/refs/heads/master/ADBKeyboard.apk"

Backup APK from the ADBKeyboard project. It allows sending Unicode characters but may not work on all devices. In most cases, there’s no need to modify it.


adbkeyboardsave_path: str = "/sdcard/ADBKeyboard.apk"

The download path for the APK from the ADBKeyboard project project. In most cases, there’s no need to modify it.


validadbkeyboards: tuple = ("com.android.adbkeyboard/.AdbIME", "com.github.uiautomator/.AdbKeyboard",)

Possible package names for ADBKeyboard.

In most cases, there’s no need to modify them.

Creating an instance

from cyandroemu import TermuxAutomation, clean_zombies

import pandas as pd from time import sleep as timesleep import atexit

Ensure background parsers and shells are terminated on exit

atexit.register(clean_zombies)

Load parsers (first time may take ~5 mins due to download and compilation)

parsers = TermuxAutomation.loadparsersordownloadand_compile("g++")

Detect input devices dynamically (returns a pandas DataFrame)

dfdevices = TermuxAutomation.findsuitabledevicesforinputevents() print(df_devices) screenwidth, screenheight = TermuxAutomation.getresolutionof_screen()

On VMware and BlissOS, device order may change after a reboot, so hardcoding is avoided.

If device order doesn't change on your emulator, you can hardcode the path, e.g.:

mouse_device = "/dev/input/event4"

te = TermuxAutomation( parsers=parsers, mousedevice=dfdevices.loc[ (dfdevices["max"].str.len() == 2) & (dfdevices["type"] == "mouse") ]["path"].iloc[0], keyboarddevice=dfdevices.loc[ (dfdevices["keysfound"]) & (df_devices["type"] == "keyboard") ]["path"].iloc[0], mousedevicemax=df_devices.loc[ (dfdevices["max"].str.len() == 2) & (dfdevices["type"] == "mouse") ]["max"].iloc[0][0], screenheight=screenheight, screenwidth=screenwidth, )

Clean up any leftover background processes (e.g., uiautomator2 server) from earlier automations.

atexit should handle this, but "Doppelt genaeht haelt besser :)" (German proverb - double-stitched holds better).

te.kill_zombies()


Automation - it's all about pandas DataFrames

Most automation tools implement their own logic for finding elements, which often looks like this:

self.find(text="Some text").children[0].click()

That looks beautiful and very Pythonic, but most of the time, it’s just unreliable — mainly when the attributes and positions of objects vary, or when the objects aren’t loaded on the screen yet.

Instead of bothering you with my own "great" ideas, I decided to rely on battle-tested solutions: pandas DataFrames.

With DataFrames, you can leverage powerful features like:

  • Fast sorting algorithms
  • All kinds of comparisons
  • Regular expressions (regex)
  • Custom filter functions
If you know how to work with pandas DataFrames, you basically already know everything you need to automate whatever you want. If not, you can learn everything from the official documentation: https://pandas.pydata.org/docs/ That’s where I got 95% of my pandas knowledge from.

Pretty Print

The default repr and str functions in pandas are not ideal for displaying DataFrames, which is why they’ve been monkey-patched to ensure the entire DataFrame is pretty-printed.

df = te.getdfuiautomator2(with_screenshot=True)
print(df)

Now, when you print the DataFrame, you’ll see the complete content neatly formatted, making it easier to analyze UI elements. For a line-break-free experience, I recommend using the VTM terminal


Example of a pandas DataFrame in the VTM terminal

Video 1


Getting screenshots of each element

In the example above, the elements are very easy to locate. However, this is not always the case. You might want to see a screenshot of each element to write your script faster. In this case, you can use the following command on the device:

df.bbsavescreenshotsaspng("/sdcard/uiautomator2screenshots")

Then, pull the screenshots using ADB to review them on your computer:

adb -s 192.168.115.131:5555 pull /sdcard/uiautomator2screenshots

The screenshot filenames correspond to the location of the elements in the DataFrame. For example, if you want to locate the third element (index 2), simply run:

df.iloc[2]
This will extract the element’s information, allowing you to build your pandas query from there.

Example of element screenshots

Video 1



The Backends


Uiautomator2 Backend

| Advantages ✅ | Disadvantages ❌ | |------------------------------------------------|----------------------------------------------------------| | Very fast parsing | Blocks other parsers like the Logcat parser and traditional UIAutomator | | Never fails due to excessive screen movement (unlike UIAutomator) | Requires APKs to be installed | | Includes both element text and description | The server needs to run in the background | | Great for web scraping and interacting with web elements | Automation might be detected when used with installed apps | | Runs on any emulator | Useless with specific engines like the Unreal Engine |


Video - in action

Video 1


Python Code

from cyandroemu import TermuxAutomation, clean_zombies
import pandas as pd
from time import sleep as timesleep
import atexit

Ensure all background processes are terminated on exit

atexit.register(clean_zombies)

Load parsers (first time may take ~5 mins due to download/compilation)

parsers = TermuxAutomation.loadparsersordownloadand_compile("g++")

Detect input devices dynamically (Necessary on BlissOS 16 Go with VMWare)

dfdevices = TermuxAutomation.findsuitabledevicesforinputevents() screenwidth, screenheight = TermuxAutomation.getresolutionof_screen()

Initialize TermuxAutomation with dynamic device paths

te = TermuxAutomation( parsers=parsers, mousedevice=dfdevices.loc[ (dfdevices["max"].str.len() == 2) & (dfdevices["type"] == "mouse") ]["path"].iloc[0], keyboarddevice=dfdevices.loc[ (dfdevices["keysfound"]) & (df_devices["type"] == "keyboard") ]["path"].iloc[0], mousedevicemax=df_devices.loc[ (dfdevices["max"].str.len() == 2) & (dfdevices["type"] == "mouse") ]["max"].iloc[0][0], screenheight=screenheight, screenwidth=screenwidth, )

Kill any leftover background processes

te.kill_zombies()

You can install the APK using:

te.downloadandinstalluiautomator2apks()

Ensure elements are loaded on the screen instead of relying solely on sleep

df = pd.DataFrame() while df.empty: # First DataFrame load may take ~5 seconds (UIAutomator2 server startup) # For production scripts, set with_screenshot=False for better performance # You can also pass these kwargs to temporarily change the default paramenters passed to the class constructor (valid for all backends, but not recommended) # If you pass anything else than None, it will override the default parameters once. # addinputtap=None, # addsendeventmouse_click=None, # addsendeventtap=None, # addmouseaction=None, # x_column=None, # y_column=None, # mouse_device=None, # touch_device=None, # touchdevicemax=None, # mousedevicemax=None, # input_cmd=None, # sendevent_path=None, # screen_height=None, # screen_width=None, # mouseactionexe=None, # sh_exe=None, # su_exe=None, # kwargs=None, # timeout=None, df = te.getdfuiautomator2(with_screenshot=True) # Filter elements to target the TikTok app df = df.loc[ (df.aa_text == "TikTok") & (df.aacontentdesc == "TikTok") & (df.aa_clickable == 1) ]

Click the first matching element using input tap

Optional: Add offset like df.aainputtap.iloc0

df.aainputtap.iloc[0]()

Clear DataFrame for the next loop

df = pd.DataFrame()

optional sleep

timesleep(2)

Repeating the same process for other UI elements

while df.empty: df = te.getdfuiautomator2(with_screenshot=True) df = df.loc[ (df.aa_text == "Already have an account? Log in") & (df.aa_clazz == "android.widget.Button") & (df.aacontentdesc == "") ] df.aainputtap.iloc[0]() df = pd.DataFrame() timesleep(2) while df.empty: df = te.getdfuiautomator2(with_screenshot=True) df = df.loc[ (df.aa_text == "Use phone / email / username") & (df.aa_clazz == "android.widget.TextView") & (df.aacontentdesc == "") ] df.aainputtap.iloc[0]() df = pd.DataFrame() timesleep(2) while df.empty: df = te.getdfuiautomator2(with_screenshot=True) df = df.loc[ (df.aa_text == "Email / Username") & (df.aa_clazz == "android.widget.TextView") & (df.aacontentdesc == "") ] df.aainputtap.iloc[0]() df = pd.DataFrame() timesleep(2)

Send text input naturally using a lightweight Cython class

In this example, call is used directly to enter the email once

te.getcmdsendtextnatural("myemailtest@gmail.com")()


Example of a Pandas DataFrame (column width cropped to 30 chars)

|index |aaindex |aaindent |aatext |aaresourceid |aaclazz |aapackage |aacontentdesc |aacheckable |aachecked |aaclickable |aaenabled |aafocusable |aafocused |aascrollable |aalongclickable |aapassword |aaselected |aavisibletouser |aabounds |aadrawingorder |aahint |aadisplayid |aalineindex |aachildren |aaparents |aastartx |aastarty |aaendx |aaendy |aacenterx |aacentery |aawidth |aaheight |aaarea |aawhrelation |aainputtap |aasendeventmouseclick |aasendeventtap |aamouseaction |aa_screenshot | |------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------|------------------------------| |0 |0 |4 | |com.android.systemui:id/status|android.widget.FrameLayout |com.android.systemui | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[0,0][1024,24] |1 | |0 |1 |() |() |0 |0 |1024 |24 |512 |12 |1024 |24 |24576 |42.666668 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |1 |0 |6 |8:18 |com.android.systemui:id/clock |android.widget.TextView |com.android.systemui |8:18 PM |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[16,0][45,24] |2 | |0 |2 |() |() |16 |0 |45 |24 |30 |12 |29 |24 |696 |1.208333 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |2 |1 |6 | | |android.widget.ImageView |com.android.systemui |Termux notification: 1 session|0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[45,0][69,24] |4 | |0 |3 |() |() |45 |0 |69 |24 |57 |12 |24 |24 |576 |1.0 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |3 |2 |6 | | |android.widget.ImageView |com.android.systemui |Settings notification: NECVMWa|0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[69,0][93,24] |5 | |0 |4 |() |() |69 |0 |93 |24 |81 |12 |24 |24 |576 |1.0 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |4 |3 |6 | | |android.widget.ImageView |com.android.systemui |Ethernet. |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[959,1][978,23] |12 | |0 |5 |() |() |959 |1 |978 |23 |968 |12 |19 |22 |418 |0.863636 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |5 |4 |6 | |com.android.systemui:id/batter|android.widget.LinearLayout |com.android.systemui |Battery percentage unknown. |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[984,0][996,24] |16 | |0 |6 |() |() |984 |0 |996 |24 |990 |12 |12 |24 |288 |0.5 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |6 |0 |2 | | |android.widget.FrameLayout |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[0,0][1024,768] |0 | |0 |7 |() |() |0 |0 |1024 |768 |512 |384 |1024 |768 |786432 |1.333333 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |7 |0 |4 | |com.zhiliaoapp.musically:id/d4|android.view.ViewGroup |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[0,24][1024,736] |1 | |0 |8 |() |() |0 |24 |1024 |736 |512 |380 |1024 |712 |729088 |1.438202 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |8 |0 |6 | |com.zhiliaoapp.musically:id/r7|android.widget.ImageView |com.zhiliaoapp.musically |Report a problem |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[4,26][52,74] |3 | |0 |9 |() |() |4 |26 |52 |74 |28 |50 |48 |48 |2304 |1.0 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |9 |2 |6 |Skip |com.zhiliaoapp.musically:id/p6|android.widget.Button |com.zhiliaoapp.musically | |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[980,38][1008,56] |5 | |0 |10 |() |() |980 |38 |1008 |56 |994 |47 |28 |18 |504 |1.555556 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |10 |3 |6 | |com.zhiliaoapp.musically:id/tt|androidx.viewpager.widget.View|com.zhiliaoapp.musically | |0 |0 |0 |1 |1 |0 |1 |0 |0 |0 |1 |[0,77][1024,736] |2 | |0 |11 |() |() |0 |77 |1024 |736 |512 |406 |1024 |659 |674816 |1.553869 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |11 |0 |8 | |com.zhiliaoapp.musically:id/c7|androidx.recyclerview.widget.R|com.zhiliaoapp.musically | |0 |0 |0 |1 |1 |0 |0 |0 |0 |0 |1 |[267,77][758,396] |1 | |0 |12 |() |() |267 |77 |758 |396 |512 |236 |491 |319 |156629 |1.539185 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |12 |0 |10 | | |android.widget.LinearLayout |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[267,82][758,228] |1 | |0 |13 |() |() |267 |82 |758 |228 |512 |155 |491 |146 |71686 |3.363014 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |13 |0 |12 |Sign up for TikTok |com.zhiliaoapp.musically:id/ti|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |1 |0 |0 |1 |[267,122][758,150] |1 | |0 |14 |() |() |267 |122 |758 |150 |512 |136 |491 |28 |13748 |17.535715 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |14 |1 |12 |Create a profile, follow other|com.zhiliaoapp.musically:id/oe|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[267,162][758,200] |2 | |0 |15 |() |() |267 |162 |758 |200 |512 |181 |491 |38 |18658 |12.921053 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |15 |1 |10 | |com.zhiliaoapp.musically:id/cz|android.widget.Button |com.zhiliaoapp.musically |Use phone or email |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[267,228][758,272] |2 | |0 |16 |() |() |267 |228 |758 |272 |512 |250 |491 |44 |21604 |11.159091 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |16 |0 |12 |Use phone or email |com.zhiliaoapp.musically:id/c7|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[454,241][593,260] |1 | |0 |17 |() |() |454 |241 |593 |260 |523 |250 |139 |19 |2641 |7.31579 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |17 |2 |10 | |com.zhiliaoapp.musically:id/cz|android.widget.Button |com.zhiliaoapp.musically |Continue with Facebook |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[267,284][758,328] |3 | |0 |18 |() |() |267 |284 |758 |328 |512 |306 |491 |44 |21604 |11.159091 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |18 |0 |12 |Continue with Facebook |com.zhiliaoapp.musically:id/c7|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[437,297][611,316] |1 | |0 |19 |() |() |437 |297 |611 |316 |524 |306 |174 |19 |3306 |9.157895 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |19 |3 |10 | |com.zhiliaoapp.musically:id/cz|android.widget.Button |com.zhiliaoapp.musically |Continue with Google |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[267,340][758,384] |4 | |0 |20 |() |() |267 |340 |758 |384 |512 |362 |491 |44 |21604 |11.159091 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |20 |0 |12 |Continue with Google |com.zhiliaoapp.musically:id/c7|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |0 |0 |0 |0 |0 |0 |1 |[445,353][602,371] |1 | |0 |21 |() |() |445 |353 |602 |371 |523 |362 |157 |18 |2826 |8.722222 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |21 |1 |8 |By continuing with an account |com.zhiliaoapp.musically:id/rw|android.widget.TextView |com.zhiliaoapp.musically | |0 |0 |0 |1 |1 |0 |0 |0 |0 |0 |1 |[32,628][992,675] |3 | |0 |22 |() |() |32 |628 |992 |675 |512 |651 |960 |47 |45120 |20.425531 |(offsetx=0, offsety=0) |(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, durat|(offsetx=0, offsety=0, actio|[[[255 255 255] [255 255 255| |22 |2 |8 |Already have an account? Log i|com.zhiliaoapp.musically:id/s5|android.widget.Button |com.zhiliaoapp.musically | |0 |0 |1 |1 |1 |0 |0 |0 |0 |0 |1 |[0,676][1024,736] |7 | |0 |23 |() |() |0


README truncated. View on GitHub
🔗 More in this category

© 2026 GitRepoTrend · hansalemaos/cyandroemu · Updated daily from GitHub