|
15 | 15 | SaveTo is a lightweight, single-purpose Android utility that integrates into the system-wide sharing sheet to save shared files, multiple documents, or text directly to any destination chosen via the Storage Access Framework (SAF). |
16 | 16 | </p> |
17 | 17 |
|
| 18 | +<p align="center"> |
| 19 | + <a href="https://github.com/sudo-py-dev/SaveTo/releases/latest/download/app-foss-release.apk"> |
| 20 | + <img src="https://img.shields.io/badge/Download-FOSS%20APK-orange?style=for-the-badge&logo=android&logoColor=white" height="40" alt="Download FOSS APK" /> |
| 21 | + </a> |
| 22 | + |
| 23 | + <a href="https://github.com/sudo-py-dev/SaveTo/releases/latest/download/app-googlePlay-release.apk"> |
| 24 | + <img src="https://img.shields.io/badge/Download-Google%20Play%20APK-blue?style=for-the-badge&logo=googleplay&logoColor=white" height="40" alt="Download Google Play APK" /> |
| 25 | + </a> |
| 26 | +</p> |
| 27 | + |
18 | 28 | --- |
19 | 29 |
|
20 | 30 | ## Visual Preview |
|
29 | 39 |
|
30 | 40 | --- |
31 | 41 |
|
32 | | ---- |
33 | | - |
34 | 42 | ## Key Features |
35 | 43 |
|
36 | 44 | - **Seamless Share Target**: Integrates directly with Android's system share sheet, registering for `android.intent.action.SEND` and `android.intent.action.SEND_MULTIPLE` across all MIME types (`*/*`). |
|
42 | 50 |
|
43 | 51 | --- |
44 | 52 |
|
45 | | -## Technical Architecture |
46 | | - |
47 | | -The codebase is structured following clean Android architecture principles, utilizing Kotlin, Coroutines, and Android Jetpack Architecture Components. |
| 53 | +<details> |
| 54 | + <summary>🛠️ Developer & Build Guide</summary> |
48 | 55 |
|
49 | | -```mermaid |
50 | | -graph TD |
51 | | - Intent[Incoming Share Intent] --> |SEND / SEND_MULTIPLE| Activity[ShareActivity] |
52 | | - Activity --> |Resolve Metadata| VM[SaveViewModel] |
53 | | - Activity --> |Launch Picker| SAF[Storage Access Framework] |
54 | | - SAF --> |Dest URI| VM |
55 | | - VM --> |Coroutines IO Dispatcher| Save[Buffered Stream Write] |
56 | | -``` |
| 56 | + ### Technical Architecture |
57 | 57 |
|
58 | | -### Components |
| 58 | + The codebase is structured following clean Android architecture principles, utilizing Kotlin, Coroutines, and Android Jetpack Architecture Components. |
59 | 59 |
|
60 | | -- **[AndroidManifest.xml](app/src/main/AndroidManifest.xml)**: Configures the intent filters, theme settings, and application metadata. `ShareActivity` is configured with a translucent theme (`Theme.Translucent.NoTitleBar`) so that it overlays seamlessly onto the system share dialog. |
61 | | -- **[ShareActivity.kt](app/src/main/kotlin/com/save/to/ShareActivity.kt)**: Manages UI, checks URI read access, interacts with the Android Storage Access Framework (using `ActivityResultContracts.CreateDocument` and `OpenDocumentTree`), and shows standard system alerts and progress dialogs. |
62 | | -- **[SaveViewModel.kt](app/src/main/kotlin/com/save/to/SaveViewModel.kt)**: Houses the business logic for resolving source file details, performing high-performance I/O operations using a buffered stream (`8KB` buffer size), managing state, and cleaning up cache files. |
63 | | -- **[strings.xml](app/src/main/res/values/strings.xml)**: Declares all UI string resources and error messages for user-facing localization. |
| 60 | + ```mermaid |
| 61 | + graph TD |
| 62 | + Intent[Incoming Share Intent] --> |SEND / SEND_MULTIPLE| Activity[ShareActivity] |
| 63 | + Activity --> |Resolve Metadata| VM[SaveViewModel] |
| 64 | + Activity --> |Launch Picker| SAF[Storage Access Framework] |
| 65 | + SAF --> |Dest URI| VM |
| 66 | + VM --> |Coroutines IO Dispatcher| Save[Buffered Stream Write] |
| 67 | + ``` |
64 | 68 |
|
65 | | ---- |
| 69 | + ### Components |
66 | 70 |
|
67 | | -## Development & Build Requirements |
| 71 | + - **[AndroidManifest.xml](app/src/main/AndroidManifest.xml)**: Configures the intent filters, theme settings, and application metadata. `ShareActivity` is configured with a translucent theme (`Theme.Translucent.NoTitleBar`) so that it overlays seamlessly onto the system share dialog. |
| 72 | + - **[ShareActivity.kt](app/src/main/kotlin/com/save/to/ShareActivity.kt)**: Manages UI, checks URI read access, interacts with the Android Storage Access Framework (using `ActivityResultContracts.CreateDocument` and `OpenDocumentTree`), and shows standard system alerts and progress dialogs. |
| 73 | + - **[SaveViewModel.kt](app/src/main/kotlin/com/save/to/SaveViewModel.kt)**: Houses the business logic for resolving source file details, performing high-performance I/O operations using a buffered stream (`8KB` buffer size), managing state, and cleaning up cache files. |
| 74 | + - **[strings.xml](app/src/main/res/values/strings.xml)**: Declares all UI string resources and error messages for user-facing localization. |
68 | 75 |
|
69 | | -- **SDK Targets**: Min SDK `23` (Android 6.0), Target SDK `35` (Android 15) |
70 | | -- **Java Compatibility**: JDK `17` toolchain |
71 | | -- **Build Tool**: Gradle Kotlin DSL |
| 76 | + ### Development & Build Requirements |
72 | 77 |
|
73 | | -### Code Styling and Design |
| 78 | + - **SDK Targets**: Min SDK `23` (Android 6.0), Target SDK `35` (Android 15) |
| 79 | + - **Java Compatibility**: JDK `17` toolchain |
| 80 | + - **Build Tool**: Gradle Kotlin DSL |
74 | 81 |
|
75 | | -This application strictly follows modern development standards: |
76 | | -- **Coroutines for Asynchronous I/O**: Offloads stream writing tasks to `Dispatchers.IO` and uses `ensureActive()` inside loops to respect lifecycle cancellation. |
77 | | -- **No Force Unwraps**: Handles null values gracefully and relies on defensive typing contracts to prevent runtime crashes. |
78 | | -- **Resource Cleanup**: Employs `use { ... }` blocks for Kotlin `Closeable` objects, ensuring input and output streams are safely closed under all circumstances. |
| 82 | + ### Code Styling and Design |
79 | 83 |
|
80 | | -### Building the Project |
| 84 | + This application strictly follows modern development standards: |
| 85 | + - **Coroutines for Asynchronous I/O**: Offloads stream writing tasks to `Dispatchers.IO` and uses `ensureActive()` inside loops to respect lifecycle cancellation. |
| 86 | + - **No Force Unwraps**: Handles null values gracefully and relies on defensive typing contracts to prevent runtime crashes. |
| 87 | + - **Resource Cleanup**: Employs `use { ... }` blocks for Kotlin `Closeable` objects, ensuring input and output streams are safely closed under all circumstances. |
81 | 88 |
|
82 | | -Ensure you have a valid `keystore.properties` file configured in the root directory prior to building. Run the following command from the project root to compile a release build: |
| 89 | + ### Building the Project |
83 | 90 |
|
84 | | -```bash |
85 | | -./gradlew assembleRelease |
86 | | -``` |
| 91 | + Ensure you have a valid `keystore.properties` file configured in the root directory prior to building. Run the following command from the project root to compile a release build: |
87 | 92 |
|
| 93 | + ```bash |
| 94 | + ./gradlew assembleRelease |
| 95 | + ``` |
| 96 | +</details> |
0 commit comments