# Qiniu Android SDK: cloud storage uploads with a curl based HTTP/3 path

> The Qiniu Android SDK is a Java client for Qiniu cloud resource storage, published to Maven as com.qiniu:qiniu-android-sdk, with an optional curl based plugin that adds HTTP/3. Its README carries a version matrix back to Android 2.2 and a set of notes that are more instructive than the usage example, including a permissions caveat and a recommendation to pin a storage region.

**qiniu/android-sdk** — Qiniu Resource (Cloud) Storage SDK for Android

- Repository: https://github.com/qiniu/android-sdk
- Stars: 629 · Forks: 224
- Language: Java
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/qiniu-android-sdk

## A storage client with a version matrix back to Android 2.2

The Qiniu Android SDK is the resource, or cloud, storage client for Android, written in Java and published to Maven Central under the artifact com.qiniu:qiniu-android-sdk. The licence is MIT, the default branch is master, and the last push to the repository was on 2026-04-28, the same day as the v8.11.0 release.

The most informative part of the README is a compatibility table, and it is worth reading carefully because it does not just say which Android versions are supported. It maps each SDK line to a minimum Android version and to the dependency library version that line expects. The 8.11.x through 8.4.x lines need Android 4.0 or later and okhttp 4 or later. The 8.3.0, 8.2.x, 8.1.x, 8.0.x, 7.7.x, 7.6.x and 7.5.x lines need Android 5.0 or later with okhttp 4, which is an odd step, a newer SDK line asking for a newer Android floor than the lines above it. Older lines go further back, 7.4.6 to Android 4.0 with okhttp 3.12.6, 7.3.x to Android 2.3 with okhttp 3.11.0, and the 7.0.7 to 7.0.9 lines to Android 2.2 with android-async-http rather than okhttp at all.

That table is the real API of this project for a decision maker. It tells you two things at once: which line you can use given the devices you support, and which HTTP client your build will end up carrying.

The README also recommends the latest version, and the table of versions shows the project is still moving, with 8.11.0 in April 2026, 8.10.0 in March 2026 and 8.9.2 in September 2025.

## Installing: one coordinate, and an okhttp you are told to pin

There are two installation routes, and the README is firm about one detail of the second.

The first is the jar file. You copy the SDK jar into your project, download the matching jar from the Maven Central search listing, and also fetch the corresponding dependency libraries, with happy-dns linked separately from the Maven repository.

The second is the normal Gradle route, and the basic form is one line:

```gradle
implementation 'com.qiniu:qiniu-android-sdk:8.9.+'
```

Note the version range ending in a plus, which is a dynamic version: it resolves to the newest matching release rather than a pinned one. If you need to control the okhttp version, the README gives the exclusion form, and it recommends strongly using the okhttp version that Qiniu ships with:

```gradle
implementation ('com.qiniu:qiniu-android-sdk:8.9.+'){
    exclude (group: 'com.squareup.okhttp3', module: 'okhttp')
}
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
```

The exclusion syntax matters because the SDK and your application would otherwise both pull okhttp into the same build, and the version that lands on the classpath is the one that decides which HTTP stack actually runs. The README also notes that if you use Android 4.x, the okhttp version should be adjusted to 3.12 or later.

The repository itself is a Gradle project with a library directory, a doc directory, build.gradle, settings.gradle, gradle.properties, an mvn_push.gradle for publishing, the gradlew wrappers, a CHANGELOG.md, codecov.yml, an AGENTS.md, a CLAUDE.md and a Contributing.md.

## UploadManager is created once and reused

The usage model is a single class, and the README makes one point about its lifecycle: UploadManager can be created once and used for the lifetime of the application.

The example shows the shape of an upload. You construct an UploadManager, then call put with the data, a key, the token and a completion handler:

```java
import com.qiniu.android.storage.UploadManager;
...
UploadManager uploadManager = new UploadManager();
uploadManager.put("Hello, World!".getBytes(), "hello", token,
new UpCompletionHandler() {
    @Override
    public void complete(String key, ResponseInfo info, JSONObject response) {
        LogUtil.i(info);
    }
}, null);
...
```

Two details in that snippet are worth flagging. The first argument is a byte array, and the README notes that the data can equally be a file path or a file. The last argument is null, which in the signature is the upload options, so the defaults apply unless you pass an UploadOptions instance.

The completion handler receives the key, a ResponseInfo and the raw JSON response, and the example simply logs the ResponseInfo. That is the right shape to copy: the handler is where you decide what a successful upload means for your app, and the response object carries the server side details.

The token in the example is described as obtained from the server side SDK, and the fuller example in the FAQ section makes the same point more strongly, recommending that the upload token be fetched through a request to your own service rather than hard coded. A token embedded in an application is a token that ships to every device, so this is the security decision that matters most in an integration.

The demo code is in a separate repository, qiniudemo/qiniu-lab-android.

## HTTP/3 arrives as a separate curl plugin

The most distinctive feature of the SDK is the HTTP/3 support, and it is packaged the right way round. Instead of bundling a second HTTP stack into the core, the curl based client lives in its own artifact, qiniu-android-curl-plugin, and the README says the http3 client plugin requires Android SDK v8.5.0 or later.

Installing it means removing the normal dependency and adding the plugin:

```java
implementation 'com.qiniu:qiniu-android-curl-plugin:1.0.0'
```

And using it means building a CurlClient and passing it into the SDK configuration:

```java
import com.qiniu.client.curl.CurlClient;
import com.qiniu.android.storage.Configuration;
import com.qiniu.android.storage.UploadManager;

CurlClient client = new CurlClient(caPath);
Configuration config = new Configuration.Builder()
                .requestClient(client)
                .build();
UploadManager manager = new UploadManager(config);
```

The Configuration.Builder pattern is the seam that makes this possible: the transport is injected, so the same upload code runs over either client. That is a well designed extension point, and it is also why the plugin can require a newer SDK without forcing the upgrade on everyone.

One option deserves attention. The CurlClient constructor takes a caPath, the local path of an SSL certificate, and the comment explains that if it is not defined, the CA bundled inside the SDK is used, with the certificate sourced from the curl project at https://curl.se/ca/cacert.pem. For most applications the bundled certificate is the sane default. For an application that has to trust an internal certificate authority, the caPath option is how you point the client at your own trust root.

## The notes section: signal strength, DNS prefetch and the region hint

The most useful content in the README is a list of notes, and three of them describe behaviour you would otherwise only learn by reading the source.

The first is the signal strength helper. Between versions 7.6.2 and 8.3.2 the SDK calls AndroidNetwork.getMobileDbm() to obtain the mobile signal strength, and doing so requires two permissions, and the README states they take effect when the API is 18 or above:

```xml
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
```

This is the sharpest limitation in the project. A feature that reads the mobile signal strength requires location permissions, and the README's own demo adds ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION to the manifest. Asking users for location access to upload a photo is a hard sell, and the feature is only available in that narrow version range anyway.

The second note is about DNS. From version 7.5.0 the SDK added DNS prefetching and a caching strategy, aimed at reducing DNS resolution errors. That is a network layer improvement and it is invisible in the API, which is exactly why it is documented.

The third is a recommendation with a cost benefit framing: if you can determine the region, specify a fixed region, because that saves one network request and removes one chance of an error. The reasoning is straightforward, a region lookup is a round trip, and a fixed region turns it into a constant.

Taken together, these notes describe an SDK that tries to reduce round trips, and the price is a set of permissions and version constraints that a newer Android target makes increasingly awkward.

## Testing on a device, and where the repository stands

The test section is one command, and it is an instrumented run rather than a unit test run:

```bash
$ ./gradlew connectedAndroidTest
```

connectedAndroidTest means the suite runs against a connected device or emulator, which is expected for a library that depends on the platform's networking and file behaviour, and it does mean you need a device in the loop for a full verification.

The repository carries a build status badge for a workflow named Run Test Cases and a codecov badge, so the test suite is executed in CI and coverage is tracked.

On maintenance, the numbers are mixed in a way worth stating plainly. The last push was on 2026-04-28, which is about six months before the current date, and the release history shows v8.11.0 on the same day, v8.10.0 on 2026-03-26 and v8.9.2 on 2025-09-24. So the project is not dormant, but the gap between the last release and today is the kind of interval where you should check the CHANGELOG.md and the doc directory rather than assume a fix has landed.

One inconsistency in the README is a small warning sign. The notes recommend using the latest version and name 8.10.0, while the release history and the compatibility table already list 8.11.0. That suggests the notes section is maintained less often than the release process, which is worth keeping in mind when you rely on the documentation for a specific version.

The licence is MIT, with the text in the LICENSE file at the root and a badge in the README, so there is no copyleft obligation to carry into a commercial application that depends on this SDK.

## Conclusion

Adopt the Qiniu Android SDK if your application uploads to Qiniu storage and you specifically need the curl based HTTP/3 path, since that is the one capability the upstream libraries do not give you and it is packaged as a separate plugin so the core stays small. Do not adopt it if your uploads are infrequent enough that the default HTTP stack is fine, and do not build a new integration on the signal strength helper, since the README limits it to a narrow version range. Verify first that the okhttp version your application already uses is compatible, because the README asks you to use the Qiniu supplied okhttp and pin it explicitly, that the region you upload to is fixed rather than discovered at runtime, and that the permissions you declare match the version range you depend on.

## FAQ

### How do I add the Qiniu Android SDK to my Gradle project?

Add the dependency implementation 'com.qiniu:qiniu-android-sdk:8.9.+', or copy the SDK jar into your project directly. If you need to control the okhttp version, use the exclusion form and add your own okhttp dependency, which the README strongly recommends.

### Which Android versions does the Qiniu Android SDK support?

The compatibility table in the README maps each line to a minimum Android version: the 8.11.x to 8.4.x lines need Android 4.0 or later, the 8.3.0 to 7.5.x lines need Android 5.0 or later, and the 7.x lines go back to Android 2.2 with android-async-http.

### How do I enable HTTP/3 with the Qiniu Android SDK?

Remove the qiniu-android-sdk dependency and add the curl plugin instead, implementation 'com.qiniu:qiniu-android-curl-plugin:1.0.0', which requires SDK version 8.5.0 or later. Then build a CurlClient and pass it through Configuration.Builder().requestClient(client) into the UploadManager.

### Why does the Qiniu Android SDK need location permissions?

Between versions 7.6.2 and 8.3.2 the SDK calls AndroidNetwork.getMobileDbm() to read the mobile signal strength, which requires ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION and takes effect on API 18 and above. The README does not document this outside the notes section.

## Sources

- [Issues](https://github.com/qiniu/android-sdk/issues)
- [License: MIT](https://github.com/qiniu/android-sdk/blob/master/LICENSE)
- [qiniu/android-sdk on GitHub](https://github.com/qiniu/android-sdk)
- [README](https://github.com/qiniu/android-sdk/blob/master/README.md)
- [Releases](https://github.com/qiniu/android-sdk/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/qiniu-android-sdk
