diff --git a/src/routes/docs/tutorials/android/step-1/+page.markdoc b/src/routes/docs/tutorials/android/step-1/+page.markdoc index 17a7350925..0ac423e796 100644 --- a/src/routes/docs/tutorials/android/step-1/+page.markdoc +++ b/src/routes/docs/tutorials/android/step-1/+page.markdoc @@ -1,17 +1,26 @@ --- layout: tutorial -title: Coming soon +title: Recipewrite - a Recipe sharing app description: Learn to build an Android app with no backend code using an Appwrite backend. framework: Android step: 1 -draft: true +difficulty: beginner --- -Improve the docs, add this guide. +**Recipewrite**: an android app to share and find all the delicious recipes that left you licking your fingers. +In this tutorial, you will build Recipewrite with Appwrite, Android and Java. -We still don't have this guide in place, but we do have some great news. -The Appwrite docs, just like Appwrite, is completely open sourced. -This means, anyone can help improve them and add new guides and tutorials. +# Concepts {% #concepts %} +This tutorial will introduce the following concepts: -If you see this page, **we're actively looking for contributions to this page**. -Follow our contribution guidelines, open a PR to [our Website repo](https://github.com/appwrite/website), and collaborate with our core team to improve this page. \ No newline at end of file +1. Setting up your first project +2. Authentication +3. Databases and collections +4. Database Queries +5. Pagination + +# Prerequisites {% #prerequisites %} +1. Basic knowledge of Java. +2. Have [Java](https://www.java.com/en/) and [Android Studio](https://developer.android.com/studio) installed on your computer. + +If you are stuck at any point, you can refer to the final code repository of this tutorial [here](https://github.com/letsintegreat/Recipewrite). \ No newline at end of file diff --git a/src/routes/docs/tutorials/android/step-2/+page.markdoc b/src/routes/docs/tutorials/android/step-2/+page.markdoc new file mode 100644 index 0000000000..ef14fc4641 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-2/+page.markdoc @@ -0,0 +1,33 @@ +--- +layout: tutorial +title: Initialize project +description: Learn to build an Android app with no backend code using an Appwrite backend. +step: 2 +difficulty: beginner +--- + +# Initialize Android Studio project {% #initialize-android-studio-project %} + +Open Android Studio and click **New Project** to create a new project. Select **Empty Views Activity**, and click **Next**. + +![Empty Activity](/images/docs/tutorials/recipewrite-empty-activity.png) + +Name your project **Recipewrite**, select Java language, and minimum SDK would be **23**. + +![New Project](/images/docs/tutorials/recipewrite-new-project.png) + +# Add dependencies {% #add-dependencies %} + +Open `app/build.gradle` file, update `compileSdk` and `targetSdk` to **34**, then find `dependencies` block, and add the Appwrite dependency along with existing ones. + +``` +dependencies { + implementation 'io.appwrite:sdk-for-android:4.0.0' // Appwrite dependency + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.10.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' +} +``` \ No newline at end of file diff --git a/src/routes/docs/tutorials/android/step-3/+page.markdoc b/src/routes/docs/tutorials/android/step-3/+page.markdoc new file mode 100644 index 0000000000..d63081d926 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-3/+page.markdoc @@ -0,0 +1,68 @@ +--- +layout: tutorial +title: Setup Appwrite +description: Learn to build an Android app with no backend code using an Appwrite backend. +step: 3 +difficulty: beginner +--- + +# Create project {% #create-project %} + +Head to the [Appwrite Console](https://cloud.appwrite.io/console). + +{% only_dark %} +![Create project screen](/images/docs/quick-starts/dark/create-project.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/quick-starts/create-project.png) +{% /only_light %} + +If this is your first time using Appwrite, create an account and create your first project. + +Then, under **Add a platform**, add a **Android app**. **Package Name** can be found in app level gradle file. + +{% only_dark %} +![Add a platform](/images/docs/quick-starts/dark/add-platform.png) +{% /only_dark %} +{% only_light %} +![Add a platform](/images/docs/quick-starts/add-platform.png) +{% /only_light %} + +You can skip the optional steps. + +# Connect your app with Appwrite {% #connect-your-app-with-appwrite %} + +Create **Appwrite.java** in the same directory that contains **MainActivity.java**, this will handle our app's interaction with Appwrite server. Replace `[project-id]` with your new project's id, which can be found beside your project's name in overview tab. + +```java +public class Appwrite { + private static Client client; + private static Account account; + private static Databases databases; + + private static final String projectID = "[project-id]"; + private static final String endpoint = "https://cloud.appwrite.io/v1"; // Add local address if you are running Appwrite locally + + public static void init(Context context) { + client = new Client(context); + client.setEndpoint(endpoint); + client.setProject(projectID); + client.setSelfSigned(true); + + account = new Account(client); + databases = new Databases(client); + } +} +``` + +Finally, call this `init` method in `onCreate` method of **MainActivity.java**. + +```java +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Appwrite.init(this); +} +``` \ No newline at end of file diff --git a/src/routes/docs/tutorials/android/step-4/+page.markdoc b/src/routes/docs/tutorials/android/step-4/+page.markdoc new file mode 100644 index 0000000000..a1a5619492 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-4/+page.markdoc @@ -0,0 +1,412 @@ +--- +layout: tutorial +title: Authentication +description: Learn to build an Android app with no backend code using an Appwrite backend. +step: 4 +difficulty: beginner +--- + +# User Flow {% #user-flow %} + +This is the user flow that we are going to achieve in this page. + +![user-flow](/images/docs/tutorials/recipewrite-user-flow.png) + +Keeping the userflow in mind, let us start by initializing two new empty views activities, **AuthActivity** and **HomeActivity**. + +# Appwrite methods {% #appwrite-methods %} + +Let us implement some utility methods in **Appwrite.java**. + +**onGetAccount** + +It will be used in **MainActivity** to check if the user is already logged in or not. `coroutineCallback` is the piece of code that should be run after checking whether or not the user is logged in. + +```java +public static void onGetAccount(CoroutineCallback coroutineCallback) { + try { + /* Account.get is used to get the currently logged in user. */ + account.get(coroutineCallback); + } catch (Exception e) { + e.printStackTrace(); + } +} +``` + +**onLogin** + +This method will take in email and password, and will try to log the user in. + +```java +public static void onLogin(String email, String password, CoroutineCallback coroutineCallback) { + /* Allow the user to login into their account by providing a valid email and password combination. */ + account.createEmailSession( + email, + password, + coroutineCallback + ); +} +``` + +**onCreateAccount** + +This method will take in email, password and name, and will try to register our new user to the app. + +```java +public static void onCreateAccount(String email, String password, String name, CoroutineCallback coroutineCallback) { + try { + /* Allow a new user to register a new account */ + account.create( + ID.Companion.unique(), + email, + password, + name, + coroutineCallback + ); + } catch (AppwriteException e) { + e.printStackTrace(); + } +} +``` + +**onLogout** + +```java +public static void onLogout(CoroutineCallback coroutineCallback) { + /* Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. */ + account.deleteSession( + "current", + coroutineCallback + ); +} +``` + +# Main Activity {% #main-activity %} + +As shown in the userflow, main activity will just check if the user is already logged in or not. It will redirect accordingly. + +## **activity_main.xml** + +We just need a progress bar here. + +```xml + +``` + +## **MainActivity.java** + +We will reuse our **onGetAccount** method here. + +```java +@Override +protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO); + setContentView(R.layout.activity_main); + + /* Ensure this is the first time onCreate is called. */ + /* This will prevent Appwrite to be initialized multiple times */ + if (savedInstanceState == null) { + Appwrite.init(this); + Appwrite.onGetAccount(new CoroutineCallback<>((result, error) -> { + + Intent intent; + + if (error != null) { /* User isn't logged in. */ + intent = new Intent(this, AuthActivity.class); + } else { /* User is logged in. */ + intent = new Intent(this, HomeActivity.class); + + /* This will pass the account name to HomeActivity. */ + intent.putExtra("name", result.getName()); + } + + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + /* Launch the activity as per our user flow. */ + startActivity(intent); + + /* Finish the current activity. */ + this.finish(); + })); + } +} +``` + +# Auth Activity {% #auth-activity %} + +## **activity_login.xml** + +We will need five elements here. + +- Name field, which will dynamically be shown/hidden from UI as per the current state(Register/Login). + +```xml + +``` + +- Email field. + +```xml + +``` + +- Password field. + +```xml + +``` + +- Submit button, which will initially be called "Register" and will be renamed dynamically to "Login" as per the current state. + +```xml +