From 9021ca68b016a5f30fea11df1e4b532a0cfae15d Mon Sep 17 00:00:00 2001 From: Harshit Seksaria <37345795+letsintegreat@users.noreply.github.com> Date: Mon, 23 Oct 2023 02:25:09 +0530 Subject: [PATCH 1/3] Add tutorial for android java --- src/routes/docs/tutorials/+page.svelte | 8 +- .../tutorials/android/step-1/+page.markdoc | 24 +- .../tutorials/android/step-2/+page.markdoc | 28 + .../tutorials/android/step-3/+page.markdoc | 70 +++ .../tutorials/android/step-4/+page.markdoc | 507 ++++++++++++++++++ .../tutorials/android/step-5/+page.markdoc | 307 +++++++++++ .../tutorials/android/step-6/+page.markdoc | 116 ++++ .../tutorials/android/step-7/+page.markdoc | 158 ++++++ .../tutorials/android/step-8/+page.markdoc | 11 + .../docs/tutorials/recipewrite-user-flow.png | Bin 0 -> 300040 bytes 10 files changed, 1219 insertions(+), 10 deletions(-) create mode 100644 src/routes/docs/tutorials/android/step-2/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-3/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-4/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-5/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-6/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-7/+page.markdoc create mode 100644 src/routes/docs/tutorials/android/step-8/+page.markdoc create mode 100644 static/images/docs/tutorials/recipewrite-user-flow.png diff --git a/src/routes/docs/tutorials/+page.svelte b/src/routes/docs/tutorials/+page.svelte index 40429352e5..d8a59ab6d0 100644 --- a/src/routes/docs/tutorials/+page.svelte +++ b/src/routes/docs/tutorials/+page.svelte @@ -92,13 +92,15 @@
  • -
    +
    -

    Coming soon...

    -
    +

    + Learn Appwrite Auth, Databases, and more with Android/Java. +

    +
  • diff --git a/src/routes/docs/tutorials/android/step-1/+page.markdoc b/src/routes/docs/tutorials/android/step-1/+page.markdoc index f3e111bd41..ae720ba11e 100644 --- a/src/routes/docs/tutorials/android/step-1/+page.markdoc +++ b/src/routes/docs/tutorials/android/step-1/+page.markdoc @@ -1,15 +1,25 @@ --- 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. step: 1 +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..f22abb23b2 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-2/+page.markdoc @@ -0,0 +1,28 @@ +--- +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 %} + +1. Fire up your Android Studio + +2. Go to **File / New / New Project** + +3. Select **Empty Activity** + +4. Name your project **Recipewrite**, select Java language, and minimum SDK would be **23** + +# Add dependencies {% #add-dependencies %} + +1. Open **app/build.gradle** file + +2. Find `dependencies` block, and add the following dependencies along with existing ones + ``` + implementation 'io.appwrite:sdk-for-android:4.0.0' + ``` + +3. Update `compileSdk` and `targetSdk` to **34** in the same file \ 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..2c3ba04629 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-3/+page.markdoc @@ -0,0 +1,70 @@ +--- +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. + +Give your project a new name, and set **Project ID** to `recipewrite`. + +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**, this will handle our app's interaction with Appwrite server. + +```java +public class Appwrite { + private static Client client; + private static Account account; + private static Databases databases; + + private static final String projectID = "recipewrite"; + 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..1c02ec4da6 --- /dev/null +++ b/src/routes/docs/tutorials/android/step-4/+page.markdoc @@ -0,0 +1,507 @@ +--- +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 three new empty activities - + +- **LoginActivity** +- **RegisterActivity** +- **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. + +```java +public static void onGetAccount(Context context) { + try { + /* Account.get is used to get the currently logged in user. */ + account.get(new CoroutineCallback<>((result, error) -> { + + Intent intent; + + if (error != null) { /* User isn't logged in. */ + intent = new Intent(context, LoginActivity.class); + } else { /* User is logged in. */ + intent = new Intent(context, HomeActivity.class); + + /* This will pass the account name to HomeActivity */ + intent.putExtra("name", result.getName()); + } + + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + ((Activity) context).finish(); + })); + } 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(Context context, String email, String password) { + /* Allow the user to login into their account by providing a valid email and password combination. */ + account.createEmailSession( + email, + password, + new CoroutineCallback<>((result, error) -> { + if (error != null) { + /* Login unsuccessful */ + error.printStackTrace(); + return; + } + + /* Get current user and redirect to HomeActivity */ + onGetAccount(context); + }) + ); +} +``` + +- **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(Context context, String email, String password, String name) { + try { + /* Allow a new user to register a new account */ + account.create( + ID.Companion.unique(), + email, + password, + name, + new CoroutineCallback<>((result, error) -> { + if (error != null) { + /* Create account unsuccessful */ + error.printStackTrace(); + return; + } + + /* Log the new user in, and redirect to HomeActivity */ + onLogin(context, email, password); + }) + ); + } catch (AppwriteException e) { + e.printStackTrace(); + } +} +``` + +- **onLogout** + +```java +public static void onLogout(Context context) { + /* 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", + new CoroutineCallback<>((result, error) -> { + if (error != null) { + /* Logout unsuccessful */ + error.printStackTrace(); + return; + } + + /* Redirect to LoginActivity if logout successful */ + Intent intent = new Intent(context, LoginActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + ((Activity) context).finish(); + }) + ); +} +``` + +# 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(this); + } +} +``` + +# Login Activity {% #login-activity %} + +## **activity_login.xml** + +We will need four elements here. + +- Email field + +```xml + +``` + +- Password field + +```xml + +``` + +- Login button to submit the entered email and password + +```xml +