{"id":26520887,"url":"https://github.com/bolteu/screenshotty","last_synced_at":"2025-04-07T11:01:28.593Z","repository":{"id":47673604,"uuid":"210535773","full_name":"bolteu/screenshotty","owner":"bolteu","description":"A library for programatically capturing screenshots on Android","archived":false,"fork":false,"pushed_at":"2024-03-05T05:31:32.000Z","size":133,"stargazers_count":274,"open_issues_count":18,"forks_count":42,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-31T10:08:15.415Z","etag":null,"topics":["android","android-library","mediaprojection","pixelcopy","screen-capture","screenshot","screenshot-library","screenshots"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bolteu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-24T07:09:57.000Z","updated_at":"2025-03-17T08:08:18.000Z","dependencies_parsed_at":"2025-03-21T12:48:24.154Z","dependency_job_id":null,"html_url":"https://github.com/bolteu/screenshotty","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bolteu%2Fscreenshotty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bolteu%2Fscreenshotty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bolteu%2Fscreenshotty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bolteu%2Fscreenshotty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bolteu","download_url":"https://codeload.github.com/bolteu/screenshotty/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640459,"owners_count":20971556,"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","android-library","mediaprojection","pixelcopy","screen-capture","screenshot","screenshot-library","screenshots"],"created_at":"2025-03-21T12:29:48.726Z","updated_at":"2025-04-07T11:01:28.529Z","avatar_url":"https://github.com/bolteu.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Screenshotty\n\nThe library combines [MediaProjection](https://developer.android.com/reference/android/media/projection/MediaProjection), [PixelCopy](https://developer.android.com/reference/android/view/PixelCopy) and Canvas drawing and provides an easy-to-use API, abstracted from the Android framework and the complexities of the underlying mechanisms, to capture precisely what a user sees on their screen.\n\n[The sample app](https://github.com/bolteu/screenshotty/blob/master/sample/src/main/java/eu/bolt/screenshotty/sample/MainActivity.kt) shows how to use the library.\n\n## Gradle\nAdd this to your dependencies block.\n```\nimplementation 'eu.bolt:screenshotty:1.0.4'\n```\n\nTo use a [reactive wrapper](https://github.com/bolteu/screenshotty/new/master?readme=1#reactive-wrapper) also add:\n```\nimplementation 'eu.bolt:screenshotty-rx:1.0.4'\n```\n\nTo work with [coroutines](https://github.com/bolteu/screenshotty/new/master?readme=1#coroutines) add: \n```\nimplementation 'eu.bolt:screenshotty-coroutines:1.0.4'\n```\n\n## Wiki\n\n### General\nIf we want to capture a screenshot inside the app, the simplest approach is to draw the root view on a `Bitmap`, but\nthis approach won't work correctly if there are open dialogs, or view hierarchy contains maps or other `SurfaceView`s.\nScreenshotty uses [PixelCopy](https://developer.android.com/reference/android/view/PixelCopy) and [MediaProjection](https://developer.android.com/reference/android/media/projection/MediaProjection) to\nprovide the correct image in all these cases.\n\nFirst the library tries to make a `PixelCopy` with dialogs, retrieved via reflection, rendered on top.\n\nIf this approach fails, user will see a record screen permission dialog. Screenshotty minimizes the number of times the dialog is shown: permission has to be granted only once per process lifetime. If \"Don't show again\" option (removed in Android 10) is checked, the system will remember user's choice for all the future invocations. If the permission is granted, a `MediaProjection` API is used to take a single frame and provide it to result listeners.\n\nIn case `MediaProjection` fails, fallback strategies are invoked one-by-one until the first one succeeds to provide a Bitmap.\n\n### Usage\n\n1. Create a `ScreenshotManager`:\n\n```kotlin\nscreenshotManager = ScreenshotManagerBuilder(this)\n   .withCustomActionOrder(ScreenshotActionOrder.pixelCopyFirst()) //optional, ScreenshotActionOrder.pixelCopyFirst() by default\n   .withPermissionRequestCode(REQUEST_SCREENSHOT_PERMISSION) //optional, 888 by default\n   .build()\n```\n\n2. Make sure the object receives activity results:\n\n```kotlin\noverride fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n   super.onActivityResult(requestCode, resultCode, data)\n   screenshotManager.onActivityResult(requestCode, resultCode, data)\n}\n```\n3. Request a screenshot and observe the result:\n\n```kotlin\nval screenshotResult = screenshotManager.makeScreenshot()\nval subscription = screenshotResult.observe(\n   onSuccess = { processScreenshot(it) },\n   onError = { onMakeScreenshotFailed(it) }\n)\n```\n4. If you're no longer interested in the result (as when your `Activity` is destroyed), you can unsubscribe your observers using the object you got from `observe()`.\n\n```kotlin\noverride fun onDestroy() {\n   super.onDestroy()\n   subscription.dispose()\n}\n```\n\n### Working with result\n\nWhen you receive a `Screenshot` you can either get a `Bitmap` object from it:\n```kotlin\nfun show(screenshot: Screenshot) {\n   val bitmap = when (screenshot) {\n      is ScreenshotBitmap -\u003e screenshot.bitmap\n   }\n   screenshotPreview.setImageBitmap(bitmap)\n}\n```\nOr use `ScreenshotFileSaver` provided by the library to write the image to a file:\n```kotlin\nfun writeToFile(screenshot: Screenshot): File {\n   val fileSaver = ScreenshotFileSaver.create(Bitmap.CompressFormat.PNG)\n   val targetFile = File(context.filesDir, \"screenshot\")\n   fileSaver.saveToFile(targetFile, screenshot)\n   return targetFile\n}\n```\n\n### Reactive wrapper\n\nIf you're using [screenshotty-rx](https://github.com/bolteu/screenshotty/new/master?readme=1#gradle), you can transform your `ScreenshotManager` object into `RxScreenshotManager`:\n```kotlin\nval rxScreenshotManager = screenshotManager.asRxScreenshotManager() //or RxScreenshotWrapper.wrap(screenshotManager)\n```\n[Usage](https://github.com/bolteu/screenshotty/new/master?readme=1#usage) is exactly the same, but `makeScreenshot()` returns `Single\u003cScreenshot\u003e` instead of `ScreenshotResult`, so you can use all the expressive power of reactive composition to process the result:\n```kotlin\nsubscription = rxScreenshotManager.makeScreenshot()\n   .observeOn(Schedulers.io())\n   .map(::writeToFile)\n   .doOnSuccess(::sendScreenshotFile)\n   .observeOn(AndroidSchedulers.mainThread())\n   .subscribe(\n      onSuccess = ::onScreenshotSent,\n      onError = ::handleError\n   )\n```\n\n### Coroutines wrapper\nScreenshooty also supports [coroutines](https://github.com/bolteu/screenshotty/new/master?readme=1#gradle) by exposing the `ScreenshotManager.makeScreenshotAsync()` suspend extension function.\n```kotlin\n    screenshotManager.makeScreenshotAsync()\n``` \n[Usage](https://github.com/bolteu/screenshotty/new/master?readme=1#usage) is exactly the same, but `makeScreenshot()` is a `suspend` function.\n\n### Fallback strategies\n\nWhen constructing a `ScreenshotManager` you can add any number of objects that implement [`FallbackStrategy`](https://github.com/bolteu/screenshotty/blob/master/screenshotty-lib/src/main/java/eu/bolt/screenshotty/FallbackStrategy.kt) interface. If `PixelCopy` or `MediaProjection` fails for some reason, fallback strategies will be invoked\none by one in the order they were added, until the first one succeeds to provide a `Bitmap`.\n\nIf no strategies were added or all of them failed, the default one (that simply calls `draw` on the root view and tries to render dialogs retrieved via reflection on top) will be invoked.\n\n### Actions order\n\nWhen constructing a `ScreenshotManager` an order in which screenshot actions will be taken can be specified. By default the order is `PixelCopy` -\u003e `MediaProjection` -\u003e `Fallbacks`, but that can be easily changed.  \nNote that `Fallbacks` will still run in the order they were added in. `ScreenshotActionOrder` provides all possible actions and convenient order creators. \n\n## License\n```\nMIT License\n\nCopyright (c) 2020 Bolt Technologies OÜ\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbolteu%2Fscreenshotty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbolteu%2Fscreenshotty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbolteu%2Fscreenshotty/lists"}