Skip to content

Commit 38265ae

Browse files
committed
docs: agent-optimize README + add AGENTS.md/CLAUDE.md and IDE pointer files
1 parent 1e15700 commit 38265ae

5 files changed

Lines changed: 251 additions & 184 deletions

File tree

.cursor/rules/cloudinary.mdc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
description: Cloudinary cloudinary_android — agent guide
3+
alwaysApply: true
4+
---
5+
6+
Read and follow `AGENTS.md` in the repository root. It is the single
7+
authoritative guide for this package: build/test commands, conventions,
8+
gotchas, and when to use this SDK versus a sibling Cloudinary package.

.github/copilot-instructions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Cloudinary cloudinary_android — instructions for AI coding agents
2+
3+
Read `AGENTS.md` in the repository root and follow it. It is the single
4+
authoritative guide for this package: build/test commands, conventions,
5+
gotchas, and when to use this SDK versus a sibling Cloudinary package.

AGENTS.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# AGENTS.md — cloudinary_android
2+
3+
## What this package is (one line)
4+
Native Android client SDK (Java/Kotlin) for Cloudinary: on-device media upload via a background, retrying upload queue, plus in-app transformation and delivery URL building. Current release **3.1.2** (minSdk 21, compileSdk 34).
5+
6+
## When to use this / when NOT to use this
7+
- **Use this when:** you are in a native Android app (Java or Kotlin) and need to upload from the device (files, `Uri`, camera captures) through a background queue with retries and network policies, or build delivery/transformation URLs in-app with `MediaManager.get().url()`.
8+
- **Do NOT use this when:** you are building a **cross-platform React Native app** (use [cloudinary-react-native](https://github.com/cloudinary/cloudinary-react-native)) or doing **server-side JVM work** — signed uploads, the Admin API, signature generation (use [cloudinary_java](https://github.com/cloudinary/cloudinary_java); that is also where the server-side signature this SDK consumes is generated).
9+
- **Sibling packages:** `cloudinary_java` = server-side JVM SDK + signature generation; `cloudinary-react-native` = cross-platform mobile; [android-demo](https://github.com/cloudinary/android-demo) = full sample app to copy from. Rule of thumb: runs **on the device** → this SDK; holds the `api_secret` → server only, use `cloudinary_java`.
10+
11+
## Repo layout (multi-module Gradle)
12+
Modules (from `settings.gradle`): `:core` (URL building + upload engine), `:preprocess`, `:ui`, `:glide-integration`, `:download`, `:all` (aggregate), `:sample` (demo app). Public entry point for app code is `MediaManager`.
13+
14+
## Setup
15+
Add the dependency to your app `build.gradle`:
16+
```gradle
17+
implementation 'com.cloudinary:cloudinary-android:3.1.2'
18+
```
19+
Configuration / credentials — only `cloud_name` is needed (no `api_key`/`api_secret`). Either set it programmatically in `MediaManager.init`, or via `AndroidManifest.xml` meta-data:
20+
```xml
21+
<meta-data android:name="CLOUDINARY_URL" android:value="cloudinary://@myCloudName"/>
22+
```
23+
24+
## Minimal runnable example
25+
```java
26+
// In your Application.onCreate():
27+
Map<String, String> config = new HashMap<>();
28+
config.put("cloud_name", "myCloudName");
29+
MediaManager.init(this, config);
30+
31+
// Build a delivery URL anywhere in the app:
32+
String url = MediaManager.get().url()
33+
.transformation(new Transformation().width(100).height(150).crop("fill"))
34+
.generate("sample.jpg");
35+
36+
// Queue an unsigned upload (background queue, auto-retry).
37+
// upload() takes a file-path String, Uri, byte[], or raw-resource int — no File overload.
38+
String requestId = MediaManager.get().upload(imageFile.getAbsolutePath())
39+
.unsigned("sample_preset")
40+
.callback(callback) // any UploadCallback impl
41+
.dispatch();
42+
```
43+
44+
## Build / test commands (run these after editing)
45+
Requires **JDK 17** (per CI). Use the Gradle wrapper (`./gradlew`, `gradlew.bat` on Windows).
46+
```bash
47+
./gradlew assemble # build all modules
48+
./gradlew :core:assemble # build a single module
49+
```
50+
Tests are **instrumented** (`androidTest`) and run on a device/emulator — CI runs `connectedCheck`, not plain `test`:
51+
```bash
52+
./gradlew clean connectedCheck --stacktrace # the exact command CI runs
53+
```
54+
`connectedCheck` requires a running emulator or attached device **and** a configured account: CI exports `CLOUDINARY_URL` before running (`export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh)`). Set `CLOUDINARY_URL` (`cloudinary://<api_key>:<api_secret>@<cloud_name>`) in your environment before running tests locally. CI does not wire a lint task — the stock `./gradlew lint` exists but is not part of the project's checks.
55+
56+
## Conventions & gotchas
57+
- **`MediaManager.init()` must be called before any other SDK call** — do it in `Application.onCreate()`, not per-Activity.
58+
- **Never ship the `api_secret` in the app.** Uploads are either unsigned (upload presets) or signed by your server via a `SignatureProvider` passed to `MediaManager.init`. This SDK has no Admin API and cannot sign locally.
59+
- All uploads are **asynchronous**`dispatch()` returns a `requestId`; results arrive through `UploadCallback`. Use `UploadPolicy` / `TimeWindow` to constrain retries, network type, and run window.
60+
- **minSdk 21**, compileSdk 34 (verified in `core/build.gradle`). 3.x targets Android SDK 21 and up; do not drop below.
61+
- Multi-module: change code in the owning module (`:core` for URL/upload logic) and rebuild that module.
62+
63+
## Canonical docs (leave the repo for depth)
64+
- Android SDK guide: https://cloudinary.com/documentation/android_integration
65+
- Upload (presets, callbacks, policy): https://cloudinary.com/documentation/android_image_and_video_upload
66+
- Image / video transformation: https://cloudinary.com/documentation/android_image_manipulation
67+
- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers
68+
69+
## Agent / MCP note
70+
If a capability is also exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for code generation inside an Android app. See cloudinary/mcp-servers.
71+
72+
## Commit / PR conventions
73+
- Open issues/PRs against https://github.com/cloudinary/cloudinary_android. See `CONTRIBUTING.md`.
74+
- CI (`.github/workflows/android-build.yml`) runs `./gradlew clean connectedCheck` on push and PR — ensure instrumented tests pass on an emulator before opening a PR. The repo documents no commit-message convention, so match the existing history.

CLAUDE.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@AGENTS.md
2+
3+
# CLAUDE.md — cloudinary_android
4+
5+
## What this repo is
6+
7+
Native Android client SDK (Java/Kotlin) for Cloudinary: on-device media upload via a background, retrying queue, plus in-app transformation and delivery URL building via `MediaManager`. Current release: **3.1.2** (minSdk 21, compileSdk 34).
8+
9+
## Key constraints / gotchas
10+
11+
- **`MediaManager.init()` must be called exactly once in `Application.onCreate()`** — not per-Activity. Calling it twice throws `IllegalStateException: MediaManager is already initialized`.
12+
- **Never ship `api_secret` in the app.** Uploads use unsigned upload presets or a `SignatureProvider` that calls your server. This SDK has no Admin API and cannot sign locally.
13+
- `upload()` accepts a file-path `String`, `Uri`, `byte[]`, or raw-resource `int`**there is no `File` overload**. Use `imageFile.getAbsolutePath()` for files.
14+
- `dispatch()` is async — returns a `requestId` immediately; results arrive through `UploadCallback` (`onStart`, `onProgress`, `onSuccess`, `onError`, `onReschedule`).
15+
- Multi-module Gradle project: `:core` (URL building + upload engine), `:preprocess`, `:ui`, `:glide-integration`, `:download`, `:all` (aggregate), `:sample`. Public entry point is `MediaManager`.
16+
- `CLOUDINARY_URL` for tests: `cloudinary://<api_key>:<api_secret>@<cloud_name>`. In the manifest, only the cloud name goes in — `cloudinary://@<cloud_name>` (no secret).
17+
- CI does not wire a lint task — `./gradlew lint` exists but is not part of the project's checks.
18+
19+
## Verified build / test commands
20+
21+
Requires **JDK 17** (per CI). Use the Gradle wrapper (`./gradlew` on Linux/macOS, `gradlew.bat` on Windows).
22+
23+
```bash
24+
./gradlew assemble # build all modules
25+
./gradlew :core:assemble # build a single module
26+
```
27+
28+
Tests are **instrumented** (`androidTest`) and require a running emulator or attached device:
29+
30+
```bash
31+
export CLOUDINARY_URL=cloudinary://<api_key>:<api_secret>@<cloud_name>
32+
./gradlew clean connectedCheck --stacktrace
33+
```
34+
35+
CI runs `./gradlew clean connectedCheck` and exports `CLOUDINARY_URL` via `tools/get_test_cloud.sh` before the run. Plain `./gradlew test` does not run the instrumented suite.

0 commit comments

Comments
 (0)