Add Appwrite auth to a new Android (Java) app with a working login/register/logout UI
- Never assume project details. Ask the user for Cloud Region, Project ID, and package name.
- Use Android Studio as the development environment.
- Ensure the user creates a platform in the Appwrite Console with the correct package name.
Step 1: Create or use existing Android project
- If you already have an Android project open in Android Studio, stay in it and use it.
- Otherwise, open Android Studio and click New Project.
- Choose a project template (e.g., Empty Activity) and click Next.
- Enter the app name and package name, then click Finish.
Step 2: Create Appwrite project
- Ask the user to go to the Appwrite Console.
- If this is their first time, they should create an account and create their first project.
- Under Add a platform, add an Android app with the app's name and package name (the
applicationIdfrom the app-levelbuild.gradle).
Step 3: Add the Appwrite SDK (ask user for Project ID)
- Add the following dependency to the app-level
build.gradlefile inside the dependencies block:
Groovy
implementation "io.appwrite:sdk-for-android:8.1.0"
- Add the OAuth callback activity inside the
<application>tag inAndroidManifest.xml(replace<PROJECT_ID>with actual project ID):
XML
<manifest ...>
...
<application ...>
...
<!-- Add this inside the `<application>` tag, along side the existing `<activity>` tags -->
<activity android:name="io.appwrite.views.CallbackActivity" android:exported="true">
<intent-filter android:label="android_web_auth">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="appwrite-callback-<PROJECT_ID>" />
</intent-filter>
</activity>
</application>
</manifest>
Step 4: Create Appwrite helper class (ask user for Region and Project ID)
- Ask the user for:
- Cloud Region (e.g.,
fra,nyc) - Project ID (from Console -> Settings)
- Cloud Region (e.g.,
- Create file:
AppwriteHelper.javawith the following code (replace<YOUR_ROOT_PACKAGE_HERE>,<REGION>, and<PROJECT_ID>):
Java
package <YOUR_ROOT_PACKAGE_HERE>;
import android.content.Context;
import java.util.Map;
import io.appwrite.Client;
import io.appwrite.ID;
import io.appwrite.coroutines.CoroutineCallback;
import io.appwrite.models.Session;
import io.appwrite.models.User;
import io.appwrite.services.Account;
public class AppwriteHelper {
private static AppwriteHelper instance;
private Client client;
private Account account;
private AppwriteHelper(Context context) {
client = new Client(context)
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
.setProject("<PROJECT_ID>");
account = new Account(client);
}
public static synchronized AppwriteHelper getInstance(Context context) {
if (instance == null) {
instance = new AppwriteHelper(context.getApplicationContext());
}
return instance;
}
public interface AuthCallback<T> {
void onSuccess(T result);
void onError(Exception error);
}
public void login(String email, String password, final AuthCallback<Session> callback) {
account.createEmailPasswordSession(
email,
password,
new CoroutineCallback<>((result, error) -> {
if (error != null) {
callback.onError(new Exception(error));
return;
}
callback.onSuccess(result);
})
);
}
public void register(String email, String password, final AuthCallback<User<Map<String, Object>>> callback) {
account.create(
ID.unique(),
email,
password,
new CoroutineCallback<>((result, error) -> {
if (error != null) {
callback.onError(new Exception(error));
return;
}
callback.onSuccess(result);
})
);
}
public void logout(final AuthCallback<Object> callback) {
account.deleteSession(
"current",
new CoroutineCallback<>((result, error) -> {
if (error != null) {
callback.onError(new Exception(error));
return;
}
callback.onSuccess(result);
})
);
}
}
Step 5: Create login UI in XML
- Update
activity_main.xmllayout file:
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/textViewStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="16dp"
android:textSize="18sp"
android:visibility="gone" />
<Button
android:id="@+id/buttonLogout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Logout"
android:layout_marginBottom="16dp"
android:visibility="gone" />
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:hint="Email"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:hint="Password"
android:inputType="textPassword" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/buttonLogin"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="Login" />
<Button
android:id="@+id/buttonRegister"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="Register" />
</LinearLayout>
</LinearLayout>
Step 6: Create MainActivity
- Update
MainActivity.javawith the following code (replace<YOUR_ROOT_PACKAGE_HERE>):
Java
package <YOUR_ROOT_PACKAGE_HERE>;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.Map;
import io.appwrite.models.Session;
import io.appwrite.models.User;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private EditText editTextEmail;
private EditText editTextPassword;
private Button buttonLogin;
private Button buttonRegister;
private TextView textViewStatus;
private Button buttonLogout;
private AppwriteHelper appwrite;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Initialize Appwrite
appwrite = AppwriteHelper.getInstance(getApplicationContext());
setContentView(R.layout.activity_main);
// Initialize UI components
editTextEmail = findViewById(R.id.editTextEmail);
editTextPassword = findViewById(R.id.editTextPassword);
buttonLogin = findViewById(R.id.buttonLogin);
buttonRegister = findViewById(R.id.buttonRegister);
textViewStatus = findViewById(R.id.textViewStatus);
buttonLogout = findViewById(R.id.buttonLogout);
// Set up click listeners
buttonLogin.setOnClickListener(v -> login());
buttonRegister.setOnClickListener(v -> register());
buttonLogout.setOnClickListener(v -> logout());
}
private void login() {
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();
if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(this, "Please enter email and password", Toast.LENGTH_SHORT).show();
return;
}
appwrite.login(email, password, new AppwriteHelper.AuthCallback<Session>() {
@Override
public void onSuccess(Session result) {
runOnUiThread(() -> {
Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
showLoggedInUI(email);
});
}
@Override
public void onError(Exception error) {
runOnUiThread(() -> {
Log.e(TAG, "Login failed", error);
Toast.makeText(MainActivity.this, "Login failed: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
});
}
private void register() {
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();
if (email.isEmpty() || password.isEmpty()) {
Toast.makeText(this, "Please enter email and password", Toast.LENGTH_SHORT).show();
return;
}
appwrite.register(email, password, new AppwriteHelper.AuthCallback<User<Map<String, Object>>>() {
@Override
public void onSuccess(User<Map<String, Object>> result) {
runOnUiThread(() -> {
Toast.makeText(MainActivity.this, "Registration successful. You can now login.", Toast.LENGTH_SHORT).show();
});
}
@Override
public void onError(Exception error) {
runOnUiThread(() -> {
Log.e(TAG, "Registration failed", error);
Toast.makeText(MainActivity.this, "Registration failed: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
});
}
private void logout() {
appwrite.logout(new AppwriteHelper.AuthCallback<Object>() {
@Override
public void onSuccess(Object result) {
runOnUiThread(() -> {
Toast.makeText(MainActivity.this, "Logout successful", Toast.LENGTH_SHORT).show();
showLoginUI();
});
}
@Override
public void onError(Exception error) {
runOnUiThread(() -> {
Log.e(TAG, "Logout failed", error);
Toast.makeText(MainActivity.this, "Logout failed: " + error.getMessage(), Toast.LENGTH_SHORT).show();
});
}
});
}
private void showLoggedInUI(String email) {
editTextEmail.setVisibility(View.GONE);
editTextPassword.setVisibility(View.GONE);
buttonLogin.setVisibility(View.GONE);
buttonRegister.setVisibility(View.GONE);
textViewStatus.setVisibility(View.VISIBLE);
buttonLogout.setVisibility(View.VISIBLE);
textViewStatus.setText("Logged in as " + email);
}
private void showLoginUI() {
editTextEmail.setVisibility(View.VISIBLE);
editTextPassword.setVisibility(View.VISIBLE);
buttonLogin.setVisibility(View.VISIBLE);
buttonRegister.setVisibility(View.VISIBLE);
textViewStatus.setVisibility(View.GONE);
buttonLogout.setVisibility(View.GONE);
}
}
Step 7: Run and test
- Click Run app in Android Studio.
- Test flows:
- Register a new user
- Login with the registered user
- Logout
- Surface any Appwrite errors and fix by guiding updates to
AppwriteHelper.javaand Console settings.
Deliverables
- A running Android app with working Appwrite auth (register/login/logout)
- Files created/updated: app-level
build.gradle(dependency),AndroidManifest.xml(OAuth callback),AppwriteHelper.java,activity_main.xml,MainActivity.java