{"id":17472373,"url":"https://github.com/pranavpandey/dynamic-engine","last_synced_at":"2025-04-22T10:22:45.648Z","repository":{"id":44371194,"uuid":"95243980","full_name":"pranavpandey/dynamic-engine","owner":"pranavpandey","description":"Monitor events in the background on Android.","archived":false,"fork":false,"pushed_at":"2025-03-05T19:17:58.000Z","size":2304,"stargazers_count":33,"open_issues_count":1,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T21:25:06.147Z","etag":null,"topics":["android","call","charging","dock","events","foreground-app","headset","library","lock","monitor","service"],"latest_commit_sha":null,"homepage":"https://dynamic.pranavpandey.com","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pranavpandey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"pranavpandey","patreon":"pranavpandey","open_collective":"pranavpandeydev","ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["paypal.me/pranavpandeydev"]}},"created_at":"2017-06-23T18:00:07.000Z","updated_at":"2025-03-05T19:18:01.000Z","dependencies_parsed_at":"2024-04-14T22:01:04.538Z","dependency_job_id":"2c26f032-45d6-4472-b966-211f519f8a8b","html_url":"https://github.com/pranavpandey/dynamic-engine","commit_stats":{"total_commits":197,"total_committers":1,"mean_commits":197.0,"dds":0.0,"last_synced_commit":"3ca77170dab7cd392cc51be0210dcb8b8a27ac5a"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fdynamic-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fdynamic-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fdynamic-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pranavpandey%2Fdynamic-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pranavpandey","download_url":"https://codeload.github.com/pranavpandey/dynamic-engine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249201117,"owners_count":21229004,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","call","charging","dock","events","foreground-app","headset","library","lock","monitor","service"],"created_at":"2024-10-18T17:08:55.374Z","updated_at":"2025-04-16T16:31:34.727Z","avatar_url":"https://github.com/pranavpandey.png","language":"Java","funding_links":["https://github.com/sponsors/pranavpandey","https://patreon.com/pranavpandey","https://opencollective.com/pranavpandeydev","paypal.me/pranavpandeydev","https://paypal.me/pranavpandeydev"],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"./graphics/icon.png\" height=\"160\"\u003e\n\n# Dynamic Engine\n\n[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![Build Status](https://travis-ci.org/pranavpandey/dynamic-engine.svg?branch=master)](https://travis-ci.org/pranavpandey/dynamic-engine)\n[![Release](https://img.shields.io/maven-central/v/com.pranavpandey.android/dynamic-engine)](https://search.maven.org/artifact/com.pranavpandey.android/dynamic-engine)\n\n**A collection of tasks to monitor various events including call, lock, headset, charging, dock and \nforeground app via service on Android 2.3 (API 9) and above.**\n\n\u003e [!IMPORTANT]\n\u003e Since v0.4.0, it uses [26.x.x support libraries][android-support] so, minimum SDK will be \nAndroid 4.0 (API 14).\n\u003cbr/\u003eSince v2.0.0, it uses [AndroidX][androidx] so, first [migrate][androidx-migrate] \nyour project to AndroidX.\n\u003cbr/\u003eSince v4.1.0, it is dependent on Java 8 due to the dependency on\n[Dynamic Utils][dynamic-utils].\n\u003cbr/\u003eSince v4.4.1, it is targeting Java 17 to provide maximum compatibility.\n\u003cbr/\u003eSince v4.5.0, the minimum SDK is Android 4.4 (API 19) to comply with the latest policies.\n\n---\n\n## Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n    - [Special events](#monitor-special-events)\n    - [Foreground app](#monitor-foreground-app)\n    - [Package state](#monitor-package-state)\n    - [Events priority](#events-priority)\n    - [Accessibility](#accessibility)\n    - [Dependency](#dependency)\n- [Projects](#built-with-dynamic)\n- [License](#license)\n\n---\n\n## Installation\n\nIt can be installed by adding the following dependency to your `build.gradle` file:\n\n```groovy\ndependencies {\n    // For AndroidX enabled projects.\n    implementation 'com.pranavpandey.android:dynamic-engine:4.5.0'\n\n    // For legacy projects.\n    implementation 'com.pranavpandey.android:dynamic-engine:1.3.0'\n}\n```\n\n---\n\n## Usage\n\nIt is a collection of different tasks which can monitor various events by running a service in \nthe background. Initially, it can monitor call, lock, headset, charging, dock and foreground app \nrelated events. I will do my best to add more tasks later.\n\n\u003e For a complete reference, please read the [documentation][documentation].\n\n### Special events\n\nExtend the `DynamicEngine` service and implement the interface functions to monitor call, lock,\nheadset, charging and dock related events.\n\nOn Android 6.0 (API 23) and above, `READ_PHONE_STATE` permission must be granted for \nthe app `package` to monitor call events. If this permission is not granted then,\n`onCallStateChange(isCall)` method will never be called. For more information on the \n`runtime permissions`, please read official documentation [here][runtime permissions].\n\n```java\npublic class MonitorService extends DynamicEngine {\n\n    ...\n    \n    /**\n     * This method will be called on initializing the service so that we can get the current\n     * charging, headset and dock state.\n     *\n     * @param charging {@code true} if the device is charging or connected to a power source.\n     * @param headset {@code true} if the device is connected to a headset or a audio output\n     *                device.\n     * @param docked {@code true} if the device is docked.\n     */\n    @Override\n    public void onInitialize(boolean charging, boolean headset, boolean docked) {\n        super.onInitialize(charging, headset, docked);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when call state is changed. \n     * Either on call or the device is idle.\n     *\n     * @param call {@code true} if the device is on call.\n     *             Either ringing or answered.\n     */\n    @Override\n    public void onCallStateChange(boolean call) {\n        super.onCallStateChange(call);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when screen state is changed. \n     * Either the device screen is off or on.\n     *\n     * @param screenOff {@code true} if the device screen is off.\n     */\n    @Override\n    public void onScreenStateChange(boolean screenOff) {\n        super.onScreenStateChange(screenOff);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when lock state is changed. \n     * Either the device is in the locked or unlocked state independent of the PIN, \n     * password or any other security lock.\n     *\n     * @param locked {@code true} if the device is in the locked state or the lock screen is shown.\n     */\n    @Override\n    public void onLockStateChange(boolean locked) {\n        super.onLockStateChange(locked);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when headset state is changed. \n     * Either the device is connected to a audio output device or volume is routed through \n     * the internal speaker.\n     *\n     * @param connected {@code true} if the device is connected to a headset or a audio output\n     *                  device.\n     */\n    @Override\n    public void onHeadsetStateChange(boolean connected) {\n        super.onHeadsetStateChange(connected);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when charging state is changed. \n     * Either the device is connected to a power source using the battery.\n     *\n     * @param charging {@code true} if the device is charging or connected to a power source.\n     */\n    @Override\n    public void onChargingStateChange(boolean charging) {\n        super.onChargingStateChange(charging);\n\n        // TODO: Do any work here.        \n    }\n\n    /**\n     * This method will be called when dock state is changed. \n     * Either the device is docked or not.\n     *\n     * @param docked {@code true} if the device is docked.\n     */\n    @Override\n    public void onDockStateChange(boolean docked) {\n        super.onDockStateChange(docked);\n\n        // TODO: Do any work here.  \n    }\n    \n    ...\n}\n```\n\n### Foreground app\n\nIt can be used to monitor the foreground app to perform actions based on it. It is \ncurrently in `beta` stage so, more improvements will be done in the future.\n\nIt will not run by default to save resources. It should be started explicitly by calling the\n`setAppMonitorTask(running)`.\n\nOn Android 5.0 (API 21) and above, `PACKAGE_USAGE_STATS` permission must be granted for \nthe app `package` to monitor foreground app. If this permission is not granted then,\n`onAppChange(dynamicAppInfo)` method will never be called. For more information on \n`UsageStatsManager`, please read the official documentation [here][usage stats manager].\n\n```java\npublic class MonitorService extends DynamicEngine {\n\n    ...\n    \n    /**\n     * Enable or disable the foreground app monitor task.\n     *\n     * @param running {@code true} to start monitoring the foreground app and receive\n     *                listener callback.\n     */\n    setAppMonitorTask(boolean running);\n    \n    ...\n    \n    /**\n     * This method will be called when foreground app is changed. \n     * Use it to provide the app specific functionality in the app.\n     *\n     * @param dynamicAppInfo The dynamic app info of the foreground package.\n     */\n    @Override\n    public void onAppChange(@Nullable DynamicAppInfo dynamicAppInfo) {\n        super.onAppChange(dynamicAppInfo);\n\n        // TODO: Do any work here.\n    }\n    \n    ...\n}\n````\n\n### Package state\n\nIt can be used to monitor app updates or new installs.\n\n```java\npublic class MonitorService extends DynamicEngine {\n\n    ...\n    \n    /**\n     * This method will be called when an app package is added or changed. \n     * Useful to show a notification if an app is updated or a new app is installed.\n     *\n     * @param dynamicAppInfo The dynamic app info of the updated or added package.\n     * @param newPackage {@code true} if the package is newly added.\n     */\n    @Override\n    public void onPackageUpdated(@Nullable DynamicAppInfo dynamicAppInfo, boolean newPackage) {\n        // TODO: Do any work here.\n    }\n\n    /**\n     * This method will be called when an app package is removed. \n     * Useful to show some work when a package is removed.\n     *\n     * @param packageName The package which was removed.\n     */\n    @Override\n    public void onPackageRemoved(@Nullable String packageName) {\n        // TODO: Do any work here.\n    }\n    \n    ...\n}\n````\n\n### Events priority\n\nIt can be used to manage priority of the different events in case two or more events will occur \nsimultaneously. Use `DynamicPriority` class to set or retrieve events priority.\n\n```java\npublic class DynamicPriority {\n    \n    ...\n\n    /**\n     * Default priority for the events.\n     *\n     * 1. Call (highest)\n     * 2. Lock\n     * 3. Headset\n     * 4. Charging\n     * 5. Dock\n     * 6. App (lowest)\n     */\n    \n    /**\n     * Save events priority.\n     *\n     * @param context The context to get shared preferences.\n     * @param eventsPriority ArrayList containing events priority.\n     */\n    public static void saveEventsPriority(@NonNull Context context, \n        @NonNull ArrayList\u003cString\u003e eventsPriority);\n    \n    /**\n     * Get saved events priority after checking the device for telephony and per app \n     * functionality.\n     *\n     * @param context The context to get shared preferences.\n     *\n     * @return The saved events priority.\n     */\n    public static @NonNull ArrayList\u003cString\u003e getEventsPriority(@NonNull Context context);\n    \n    /**\n     * Reset events priority to default.\n     *\n     * @param context The context to get shared preferences.\n     */\n    public static void resetPriority(@NonNull Context context);\n    \n    ...\n\n}\n````\n\n`DynamicEngine` has some useful functions to perform operations based on the events priority.\n\n```java\npublic abstract class DynamicEngine {\n    ...\n    \n    /**\n     * Retrieve the current ongoing events.\n     *\n     * @return The list of current ongoing events.\n     */\n    protected @NonNull ArrayList\u003cString\u003e getCurrentEvents();\n    \n    /**\n     * Get the event with highest priority.\n     *\n     * @return The highest priority event that has been occurred.\n     */\n    protected @DynamicEvent String getHighestPriorityEvent();\n\n    ...\n}\n```\n\n### Accessibility\n\nIt has support for [accessibility service][accessibility service] to provide a better experience. \nIt also provides more accurate results when detecting the [foreground app][foreground app].\n\n### Dependency\n\nIt depends on the [dynamic-utils][dynamic-utils] to perform\nvarious internal operations. So, its functions can also be used to perform other useful operations.\n\n---\n\n\u003cimg src=\"./graphics/apps/pranavpandey-rotation.png\" height=\"140\"\u003e\n\n## Built with Dynamic\n\nPlease email me if you are using this library and want to feature your app here. Also, please \ncheckout the `Rotation` app to experience the full potential of this library.\n\n- [Rotation][rotation]\n\n---\n\n## Author\n\nPranav Pandey\n\n[![GitHub](https://img.shields.io/github/followers/pranavpandey?label=GitHub\u0026style=social)](https://github.com/pranavpandey)\n[![Follow on Twitter](https://img.shields.io/twitter/follow/pranavpandeydev?label=Follow\u0026style=social)](https://twitter.com/intent/follow?screen_name=pranavpandeydev)\n[![Donate via PayPal](https://img.shields.io/static/v1?label=Donate\u0026message=PayPal\u0026color=blue)](https://paypal.me/pranavpandeydev)\n\n---\n\n## License\n\n    Copyright 2017-2024 Pranav Pandey\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n\n[android-support]: https://developer.android.com/topic/libraries/support-library/revisions.html#26-0-0\n[androidx]: https://developer.android.com/jetpack/androidx\n[androidx-migrate]: https://developer.android.com/jetpack/androidx/migrate\n[documentation]: https://pranavpandey.github.io/dynamic-engine\n[runtime permissions]: https://developer.android.com/training/permissions/requesting.html\n[usage stats manager]: https://developer.android.com/reference/android/app/usage/UsageStatsManager.html\n[accessibility service]: https://developer.android.com/guide/topics/ui/accessibility/service\n[foreground app]: https://github.com/pranavpandey/dynamic-engine/blob/942aa452076c154a6fc3b9698d80b1164093958e/dynamic-engine/src/main/java/com/pranavpandey/android/dynamic/engine/DynamicEngine.java#L623\n[dynamic-utils]: https://github.com/pranavpandey/dynamic-utils\n[rotation]: https://play.google.com/store/apps/details?id=com.pranavpandey.rotation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpranavpandey%2Fdynamic-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpranavpandey%2Fdynamic-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpranavpandey%2Fdynamic-engine/lists"}