diff --git a/docs/README.md b/docs/README.md
index f8fda40..fdabb45 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,50 +1,382 @@
-# ion-android-camera
+# IONCameraLib
-Welcome to **ion-android-camera**. This repository serves as a template to create repositories used to build Android libraries. This file will guide you through that process, that is defined by two sequential steps:
+A modern, flexible and feature-rich camera and media library for Android apps. Includes advanced photo, video, and gallery management with easy integration for Kotlin and Android projects.
-1. Use the current repository as the template for the new one.
-2. Clone the new repository on our machine.
-3. Run a script that updates the created repository with the correct information.
+## Installation
-These steps are detailed in the next sections.
+### Gradle
-:warning: Every step listed here must be successfully completed before you start working on the new repository.
+Add the following to your module's `build.gradle` file:
-## Create a Repository Based on the Template
+```groovy
+dependencies {
+ implementation 'io.ionic.libs:ioncameralib:1.0.0'
+}
+```
+
+Make sure you have the appropriate Maven repository declared in your project-level `build.gradle` or `settings.gradle`:
+
+```groovy
+repositories {
+ google()
+ mavenCentral()
+}
+```
+
+## Usage
+
+### Basic Camera Operations
+
+```kotlin
+import io.ionic.libs.ioncameralib.manager.IONCAMRCameraManager
+import io.ionic.libs.ioncameralib.manager.IONCAMRGalleryManager
+import io.ionic.libs.ioncameralib.manager.IONCAMREditManager
+import io.ionic.libs.ioncameralib.manager.IONCAMRVideoManager
+import io.ionic.libs.ioncameralib.model.IONCAMRCameraParameters
+import io.ionic.libs.ioncameralib.model.IONCAMREditParameters
+import io.ionic.libs.ioncameralib.model.IONCAMRVideoParameters
+import io.ionic.libs.ioncameralib.model.IONCAMRMediaType
+
+class MainActivity : AppCompatActivity() {
+
+ private lateinit var cameraManager: IONCAMRCameraManager
+ private lateinit var galleryManager: IONCAMRGalleryManager
+ private lateinit var editManager: IONCAMREditManager
+ private lateinit var videoManager: IONCAMRVideoManager
+
+ // Store parameters to use in launcher callbacks
+ private var cameraParameters: IONCAMRCameraParameters? = null
+ private var videoParameters: IONCAMRVideoParameters? = null
+ private var editParameters: IONCAMREditParameters? = null
+
+ // Launchers must be registered at class level (before the activity starts)
+ private val cameraLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ val params = cameraParameters ?: return@registerForActivityResult
+ cameraManager.processResultFromCamera(
+ activity = this,
+ intent = result.data,
+ camParameters = params,
+ onMediaResult = { mediaResult -> println("Photo captured: ${mediaResult.uri}") },
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
+
+ private val videoLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ val params = videoParameters ?: return@registerForActivityResult
+ lifecycleScope.launch {
+ cameraManager.processResultFromVideo(
+ activity = this@MainActivity,
+ uri = result.data?.data,
+ fromGallery = params.saveToGallery,
+ isPersistent = params.isPersistent,
+ includeMetadata = params.includeMetadata,
+ onSuccess = { mediaResult -> println("Video captured: ${mediaResult.uri}") },
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
+ }
+
+ private val galleryLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ lifecycleScope.launch {
+ galleryManager.onChooseFromGalleryResult(
+ activity = this@MainActivity,
+ resultCode = result.resultCode,
+ intent = result.data,
+ includeMetadata = false,
+ onSuccess = { results -> println("Selected ${results.size} item(s)") },
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
+ }
+
+ private val editLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ val params = editParameters ?: IONCAMREditParameters(
+ editURI = null, fromUri = false, saveToGallery = false, includeMetadata = false
+ )
+ editManager.processResultFromEdit(
+ activity = this,
+ intent = result.data,
+ editParameters = params,
+ onImage = { base64 -> println("Edited image (base64): $base64") },
+ onMediaResult = { mediaResult -> println("Edited image URI: ${mediaResult.uri}") },
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setupManagers()
+ }
+
+ private fun setupManagers() {
+ val exifHelper = IONCAMRExifHelper()
+ val fileHelper = IONCAMRFileHelper()
+ val mediaHelper = IONCAMRMediaHelper()
+ val imageHelper = IONCAMRImageHelper()
+
+ cameraManager = IONCAMRCameraManager(
+ applicationId = packageName,
+ exif = exifHelper,
+ fileHelper = fileHelper,
+ mediaHelper = mediaHelper,
+ imageHelper = imageHelper
+ )
+ galleryManager = IONCAMRGalleryManager(
+ exif = exifHelper,
+ fileHelper = fileHelper,
+ mediaHelper = mediaHelper,
+ imageHelper = imageHelper
+ )
+ editManager = IONCAMREditManager(
+ applicationId = packageName,
+ exif = exifHelper,
+ fileHelper = fileHelper,
+ mediaHelper = mediaHelper,
+ imageHelper = imageHelper
+ )
+ videoManager = IONCAMRVideoManager(fileHelper = fileHelper)
+ }
+
+ // Take a photo
+ fun capturePhoto() {
+ cameraParameters = IONCAMRCameraParameters(
+ mQuality = 80,
+ targetWidth = 1024,
+ targetHeight = 768,
+ encodingType = 0, // 0 = JPEG, 1 = PNG
+ mediaType = 0,
+ allowEdit = true,
+ correctOrientation = true,
+ saveToPhotoAlbum = false,
+ includeMetadata = false
+ )
+ cameraManager.takePhoto(
+ activity = this,
+ encodingType = cameraParameters!!.encodingType,
+ launcher = cameraLauncher
+ )
+ }
+
+ // Record a video
+ fun recordVideo() {
+ videoParameters = IONCAMRVideoParameters(
+ saveToGallery = false,
+ includeMetadata = false,
+ isPersistent = true
+ )
+ cameraManager.recordVideo(
+ activity = this,
+ saveVideoToGallery = videoParameters!!.saveToGallery,
+ launcher = videoLauncher,
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
+
+ // Choose from gallery
+ fun chooseFromGallery() {
+ galleryManager.chooseFromGallery(
+ activity = this,
+ mediaType = IONCAMRMediaType.PICTURE,
+ allowMultiSelect = false,
+ limit = 1,
+ launcher = galleryLauncher
+ )
+ }
+
+ // Edit an image from URI
+ fun editURIPhoto(filePath: String) {
+ editParameters = IONCAMREditParameters(
+ editURI = filePath,
+ fromUri = true,
+ saveToGallery = false,
+ includeMetadata = false
+ )
+ editManager.editURIPicture(
+ activity = this,
+ pictureFilePath = filePath,
+ launcher = editLauncher,
+ onError = { error -> println("Error: ${error.description}") }
+ )
+ }
-First, we need to create a new repository. To accomplish this, please press the **Use this template** button available on the repository's GitHub webpage.
+ // Edit an image from Base64 string
+ fun editBase64Image(base64Image: String) {
+ editParameters = null
+ editManager.editImage(
+ activity = this,
+ image = base64Image,
+ launcher = editLauncher
+ )
+ }
-
+ // Play a video
+ fun playVideo(videoUri: String) {
+ videoManager.playVideo(
+ activity = this,
+ videoUri = videoUri,
+ onSuccess = { println("Video playback started") },
+ onError = { error -> println("Video playback error: ${error.description}") }
+ )
+ }
-Next, we have to define the new repository's name. In order to get the maximum performance of the following step, we advise you to use the **[ProjectName]Lib-Android** format for the name. The names used for the **Health and Fitness** and the **Social Logins** are valid examples of the expected format (_OSHealthFitnessLib-Android_ and _OSSocialLoginsLib-Android_ respectively).
+ // Clean temporary video files
+ fun cleanupTemporaryFiles() {
+ cameraManager.deleteVideoFilesFromCache(this)
+ }
-The following image shows an example of the creation of a repository for the Android' Payments Library.
+ override fun onDestroy() {
+ super.onDestroy()
+ cameraManager.onDestroy(this)
+ }
+}
+```
+
+### Advanced Usage Examples
+
+```kotlin
+// Multiple selection from gallery (video or photo)
+fun selectMultipleMedia() {
+ galleryManager.chooseFromGallery(
+ activity = this,
+ mediaType = IONCAMRMediaType.ALL,
+ allowMultiSelect = true,
+ limit = 10,
+ launcher = galleryLauncher
+ )
+}
+
+// High quality photo with metadata
+fun takeHighQualityPhoto() {
+ cameraParameters = IONCAMRCameraParameters(
+ mQuality = 100,
+ targetWidth = 2048,
+ targetHeight = 1536,
+ encodingType = 0, // JPEG
+ mediaType = 0,
+ allowEdit = false,
+ correctOrientation = true,
+ saveToPhotoAlbum = true,
+ includeMetadata = true
+ )
+ cameraManager.takePhoto(
+ activity = this,
+ encodingType = cameraParameters!!.encodingType,
+ launcher = cameraLauncher
+ )
+}
+
+// Video recording saved to gallery
+fun recordVideoToGallery() {
+ videoParameters = IONCAMRVideoParameters(
+ saveToGallery = true,
+ includeMetadata = false,
+ isPersistent = true
+ )
+ cameraManager.recordVideo(
+ activity = this,
+ saveVideoToGallery = videoParameters!!.saveToGallery,
+ launcher = videoLauncher,
+ onError = { error -> println("Error: ${error.description}") }
+ )
+}
+```
-
+## Key Components
-After filling up the form as needed, the last step to effectively create the repository is the click on the **Create repository from template** button.
+### Manager Classes
-
+- **`IONCAMRCameraManager`**: Handles photo capture and video recording via the device camera
+- **`IONCAMRGalleryManager`**: Handles media selection from the device gallery
+- **`IONCAMREditManager`**: Handles photo editing and cropping
+- **`IONCAMRVideoManager`**: Handles video playback
-## Clone the New Repository
+### Configuration Parameters
-After completing the previous step, the next one is something common done in every repository a developer needs to do work on: clone the repository on the local machine.
+- **`IONCAMRCameraParameters`**: Configures photo capture settings (quality, dimensions, encoding type, media type, edit, orientation correction, album saving, metadata)
+- **`IONCAMRVideoParameters`**: Configures video recording settings (save to gallery, include metadata, persistence)
+- **`IONCAMREditParameters`**: Configures image editing settings (source URI, save to gallery, metadata)
-## Run the **generator_script.sh**
+### Result Model
-To finish the process, we just have one last thing to do. Run the **generator_script.sh** script that automates a couple of changes we need to apply. It is included in the _scripts_ folder.
+All successful media operations return `IONCAMRMediaResult` objects:
-To run the script, please execute the following commands on **Terminal**:
+```kotlin
+data class IONCAMRMediaResult(
+ val type: Int, // Media type (image or video)
+ val uri: String, // File URI of the captured or selected media item
+ val thumbnail: String?, // Base64 thumbnail (if available)
+ val metadata: IONCAMRMediaMetadata?, // File metadata (if requested)
+ val saved: Boolean // Whether the file was saved to the gallery
+)
+data class IONCAMRMediaMetadata(
+ val size: Long?, // File size in bytes
+ val duration: Int?, // Duration in seconds (video only)
+ val format: String?, // File format (e.g. "jpeg", "mp4")
+ val resolution: String?, // Image/video resolution (e.g. "1920x1080")
+ val creationDate: String? // File creation date
+)
```
-cd scripts
-sh generator_script.sh
+
+### Error Handling
+
+All manager methods expose an `onError` callback that receives an `IONCAMRError`. Each error carries a numeric `code` and a human-readable `description`. Errors are grouped into categories: permission errors, user cancellations, file errors, and general processing errors. See `IONCAMRError` for the full list.
+
+```kotlin
+onError = { error ->
+ // error.code — numeric error code (e.g. for logging)
+ // error.description — human-readable message
+ showErrorAlert("Error ${error.code}: ${error.description}")
+}
```
-Here's the complete list of what the script does:
+## Permissions
+
+Add the following permissions to your app's `AndroidManifest.xml`:
+
+```xml
+
+
+
+
+
+
+
+```
+
+You must also request camera and storage permissions at runtime before invoking camera or gallery operations. Use Android's standard permission request flow or a library such as [ActivityResultContracts.RequestPermission](https://developer.android.com/reference/androidx/activity/result/contract/ActivityResultContracts.RequestPermission).
+
+## Requirements
+
+- Android API 24+
+- Android Gradle Plugin 8.7.3+
+- Kotlin 1.9.24+
+- Java 17+
+
+## License
+
+This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
+
+## Contributing
+
+1. Fork the project
+2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
+3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
+4. Push to the branch (`git push origin feature/AmazingFeature`)
+5. Open a Pull Request
+
+## Support
-- The script provides a bit of information, such as mentioning the name that it will use as the Library name (its based on the one you used while creating the repository on GitHub).
-- Requests the user for the application's package identifier. The format required is provided and needs to be complied with in order to advance.
-- It informs that the script itself will be deleted, as it is a one time execution only.
-- It performs the needed changes, replacing all placeholder's organisational identifier and library name for the ones provided by the user.
-- To conclude, the script commits and pushes the changes to the remote repository.
+- Report issues on our [Issue Tracker](https://github.com/ionic-team/ion-android-camera/issues)
diff --git a/src/main/kotlin/io/ionic/libs/ioncameralib/model/IONCAMRVideoParameters.kt b/src/main/kotlin/io/ionic/libs/ioncameralib/model/IONCAMRVideoParameters.kt
index 119a6ab..6fe39fb 100644
--- a/src/main/kotlin/io/ionic/libs/ioncameralib/model/IONCAMRVideoParameters.kt
+++ b/src/main/kotlin/io/ionic/libs/ioncameralib/model/IONCAMRVideoParameters.kt
@@ -4,5 +4,6 @@ import com.google.gson.annotations.SerializedName
data class IONCAMRVideoParameters(
@SerializedName("saveToGallery") val saveToGallery: Boolean,
- @SerializedName("includeMetadata") val includeMetadata: Boolean
+ @SerializedName("includeMetadata") val includeMetadata: Boolean,
+ @SerializedName("isPersistent") val isPersistent: Boolean = true
)