Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Change Log

## 29.0.0

* Breaking: minimum Android SDK raised from 23 to 24 (Android 7.0)
* Added: `Push` service for MQTT push messages without FCM, plus `PushReceiver` for background handling
* Added: `Topic` builder for push topics
* Added: `endpointPush` and `pushClientId` on `Client`, with `setPushEndpoint` and `setPushClientId`
* Added: `Apps` service for managing OAuth2 apps, keys, secrets and installations
* Added: `Oauth2` service for using Appwrite as an OAuth2/OIDC provider
* Added: `Avatars.updatePhoto` and `Avatars.deletePhoto`
* Added: `duration` parameter to `Account.createEmailPasswordSession`
* Added: `current` parameter to `Account.deleteSessions`
* Added: `total` parameter to `Account.listSessions`, `Locale` list methods and `listTransactions`
* Added: `WEBFLOW` value to `OAuthProvider`
* Added: `toMap()` and `toJson()` on `Query` and `Operator`
* Updated: SDK manifest merges Push permissions, a foreground service and a boot receiver into apps
* Updated: narrower Netty keep rules, raising the R8 obfuscation and optimization scores Google Play reads
* Updated: added the shaded `hivemq-mqtt-client` dependency for `Push`, with consumer R8 rules
* Fixed: `Query` and `Operator` serialize correctly under R8 instead of producing `{}`
* Fixed: Realtime delivers events and error messages under R8
* Fixed: session cookies saved under R8 stay readable after an app update
* Fixed: `ID.unique()` and `InputFile.fromFile` no longer crash on Android 7.x
* Fixed: Kotlin and Java examples now compile
* Fixed: unsubscribing one of several subscriptions on a topic stops its callback

## 28.0.0

* Breaking: removed `Account.listLogs` and the `Log`, `LogList` models
Expand Down
45 changes: 43 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ repositories {
Next, add the dependency to your project's `build.gradle(.kts)` file:

```groovy
implementation("io.appwrite:sdk-for-android:28.0.0")
implementation("io.appwrite:sdk-for-android:29.0.0")
```

### Maven
Expand All @@ -49,11 +49,52 @@ Add this to your project's `pom.xml` file:
<dependency>
<groupId>io.appwrite</groupId>
<artifactId>sdk-for-android</artifactId>
<version>28.0.0</version>
<version>29.0.0</version>
</dependency>
</dependencies>
```

### Code shrinking (R8)

The SDK ships the R8 rules it needs, so no extra configuration is required. Your own classes
that the SDK fills from JSON (the `nestedType` of documents, rows and preferences, and the
`payloadType` of Realtime subscriptions) are read by Gson through reflection. Annotate them
with `@Keep` so R8 keeps their fields:

```kotlin
@Keep
data class Note(val title: String, val body: String)
```

### Push notifications

#### Background delivery

A subscription with `background = true` keeps delivering after the app is backgrounded, its
process is killed, or the device restarts, until it is unsubscribed or `push.close()` is
called (do this on sign-out). No service is kept running: a scheduled job and alarm wake the
app every 15 to 60 seconds to reconnect, and the broker replays what was sent in between
(`retry = true`). It reconnects with the credential saved at subscribe time, so use a session
(`client.setSession(...)`), not a short-lived JWT.

When no in-app callback is listening, each message is posted as a notification that opens
your launch activity with `Push.EXTRA_TOPIC` and `Push.EXTRA_PAYLOAD` in its extras. Set its
icon with `<meta-data android:name="io.appwrite.push.notification_icon" android:resource="@drawable/..." />`
in your `<application>`. To handle these messages in code, subclass `PushReceiver` and declare
it with the `io.appwrite.push.MESSAGE` action (see its docs).

Doze delays the scheduled runs. They are more punctual when your app may schedule exact
alarms (`SCHEDULE_EXACT_ALARM`) or is exempt from battery optimisation; both are your app's
choice and subject to Google Play policy, and the SDK uses them when granted. For immediate delivery even after a kill and
during Doze, call `push.setForeground(true)` from the foreground: it adds a foreground service
with a quiet ongoing notification. If you never enable it, you can remove the service from
your merged manifest, so the Play Console does not ask you to declare it:

```xml
<service android:name="io.appwrite.services.PushService" tools:node="remove" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" tools:node="remove" />
```


## Getting Started

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Account account = new Account(client);
account.createEmailPasswordSession(
"email@example.com", // email
"password", // password
60L, // duration (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/java/account/create-id-token-session.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ account.createIdTokenSession(
"<ID_TOKEN>", // idToken
"<NONCE>", // nonce (optional)
"<ACCESS_TOKEN>", // accessToken (optional)
0, // accessTokenExpiry (optional)
0L, // accessTokenExpiry (optional)
"<NAME>", // name (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/java/account/create-jwt.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Client client = new Client(context)
Account account = new Account(client);

account.createJWT(
0, // duration (optional)
0L, // duration (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
Expand Down
18 changes: 11 additions & 7 deletions docs/examples/java/account/delete-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ Client client = new Client(context)

Account account = new Account(client);

account.deleteSessions(new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
account.deleteSessions(
false, // current (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

Log.d("Appwrite", result.toString());
}));
```
18 changes: 11 additions & 7 deletions docs/examples/java/account/list-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ Client client = new Client(context)

Account account = new Account(client);

account.listSessions(new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}
account.listSessions(
false, // total (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

Log.d("Appwrite", result.toString());
}));
```
27 changes: 27 additions & 0 deletions docs/examples/java/apps/create-installation-token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.createInstallationToken(
"<APP_ID>", // appId
"<INSTALLATION_ID>", // installationId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
26 changes: 26 additions & 0 deletions docs/examples/java/apps/create-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.createKey(
"<APP_ID>", // appId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
26 changes: 26 additions & 0 deletions docs/examples/java/apps/create-secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.createSecret(
"<APP_ID>", // appId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
44 changes: 44 additions & 0 deletions docs/examples/java/apps/create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.create(
"<APP_ID>", // appId
"<NAME>", // name
List.of(), // redirectUris
"<DESCRIPTION>", // description (optional)
"https://example.com", // clientUri (optional)
"https://example.com", // logoUri (optional)
"https://example.com", // privacyPolicyUrl (optional)
"https://example.com", // termsUrl (optional)
List.of(), // contacts (optional)
"<TAGLINE>", // tagline (optional)
List.of(), // tags (optional)
List.of(), // images (optional)
"https://example.com", // supportUrl (optional)
"https://example.com", // dataDeletionUrl (optional)
List.of(), // postLogoutRedirectUris (optional)
false, // enabled (optional)
"public", // type (optional)
false, // deviceFlow (optional)
"<TEAM_ID>", // teamId (optional)
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
27 changes: 27 additions & 0 deletions docs/examples/java/apps/delete-installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.deleteInstallation(
"<APP_ID>", // appId
"<INSTALLATION_ID>", // installationId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
27 changes: 27 additions & 0 deletions docs/examples/java/apps/delete-key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.deleteKey(
"<APP_ID>", // appId
"<KEY_ID>", // keyId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
27 changes: 27 additions & 0 deletions docs/examples/java/apps/delete-secret.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
```java
import android.util.Log;

import io.appwrite.Client;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.services.Apps;

Client client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint
.setProject("<YOUR_PROJECT_ID>"); // Your project ID

Apps apps = new Apps(client);

apps.deleteSecret(
"<APP_ID>", // appId
"<SECRET_ID>", // secretId
new CoroutineCallback<>((result, error) -> {
if (error != null) {
error.printStackTrace();
return;
}

Log.d("Appwrite", result.toString());
})
);

```
Loading