Amazon Web Services 한국 블로그

AWS Amplify를 이용한 Android 앱 개발 실습 – 1부

이 글은 AWS Amplify 개발 도구를 사용하여 AWS 클라우드 기반 Android 모바일 앱을 제작하는 방법에 대한 실습 시리즈입니다.

여러분이 제일 좋아하는 애완 동물 목록을 표시하기 위한 Android 모바일 앱을 개발한다고 가정해 봅시다. 사용자 경험을 높여줄 프론트 엔드 사용자 경험에 집중 하기 위해 중요한 기능 중 하나인 애완 동물 데이터를 나열, 생성 및 저장하는 API를 설정하는 백엔드 서버 인프라를 관리 및 운영하고 싶지는 않습니다. 또한, 각 사용자가 자신의 애완 동물을 추가할 수 있도록 사용자 인증 기능을 별도로 구현하지 않고 손쉽게 설정하고 싶습니다.

즉, 오로지 Android 앱 개발 작업에 집중하고 싶다면, 어떻게 해야 할까요? 이 글에서는 이를 위해 AWS Amplify를 사용하여 손쉽게 서버리스 모바일 앱을 개발하기 위한 제작하기 단계별 실습 방법을 살펴 보겠습니다.

우리는 다음 작업을 수행하는 방법을 설명합니다.

  • AWS AppSync가 지원하는 GraphQL API를 추가합니다.
  • Amazon Cognito를 통해 사용자 인증 메커니즘을 추가합니다.
  • RecyclerView에서 애완 동물 목록을 쿼리하고 표시할 수 있습니다.
  • 새 애완 동물 데이터를 추가하고 백엔드에서 데이터를 유지하도록 설정합니다.

시작하기 – 새로운 Android 프로젝트 설정하기

사전 조건

안드로이드 앱 개발을 시작하려면 워크 스테이션에 Java JDK를 설치해야 합니다. Android Studio를 다운로드하여 설치하고 Android SDK 관리자에서 Android 6.0 SDK(API 레벨 23 이상)를 다운로드합니다.

또한 에뮬레이터 이미지도 다운로드합니다. 이를 위해 Android Studio에서 AVD Manager 를 선택해야 합니다. + Create Virtual Device를 선택하고 지침에 따라 설치를 완료합니다.

새로운 Android 프로젝트 만들기

시작하려면 먼저 새로운 Android를 만들어야 합니다. 다음과 같이 새로운 Android 프로젝트를 만듭니다.

전화 및 태블릿을 선택하고 API 23: Android 6.0 (Marshmallow)을 선택하고 다음을 클릭하십시오.

모바일에 활동 추가 화면에서 기본 활동을 선택하십시오. 다음을 선택하고 기본값을 유지한 다음 마침을 선택하여 프로젝트 설정을 완료합니다.

AWS AppSync SDK 가져오기 및 앱 구성

새로운 Android 프로젝트에서 AWS AppSync를 사용하려면 프로젝트build.gradle 파일을 수정하고 빌드 스크립트에 다음 종속성을 추가합니다.

classpath 'com.amazonaws:aws-android-sdk-appsync-gradle-plugin:2.6.+'

다음으로 app build.gradle에서 'com.amazonaws.appsync'와 AWS AppSync 및 MqttServices에 대한 종속성을 적용 플러그인의 플러그인에 추가합니다.

그 결과, build.gradle은 다음과 같이 나타나야 합니다.

apply plugin: 'com.android.application'
apply plugin: 'com.amazonaws.appsync'
android {
    // ... typical items
}
dependencies {
    // ... typical dependencies

    implementation 'com.amazonaws:aws-android-sdk-appsync:2.6.+'
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}

마지막으로 네트워크 호출 및 오프라인 상태에 대한 <uses-permissions>에 대한 업데이트를 통해 AndroidManifest.xml을 업데이트합니다. 또한 구독을 사용할 수 있도록 MqttService에 <application> 아래에 <service> 항목을 추가하십시오.

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

        <!--other code-->

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service android:name="org.eclipse.paho.android.service.MqttService" />

        <!--other code-->
    </application>

프로젝트를 제작하고 문제가 없는지 확인합니다.

AWS Amplify CLI 설치 및 새로운 AWS Amplify 프로젝트 초기화

이제 AWS Amplify CLI를 설치하고 Android 프로젝트와 통합하여 Amplify CLI 구 체인을 최대한 활용할 수 있습니다.

AWS Amplify CLI 설치

터미널을 열고 명령줄에서 다음을 실행합니다. 이미 AWS Amplify CLI를 설치한 경우 명령을 다시 실행하여 최신 업데이트를 받으십시오.

npm install -g @aws-amplify/cli -update

AWS Amplify 프로젝트 초기화

이제 Android 앱을 위한 새로운 AWS Amplify 프로젝트를 초기화해 봅시다.

cd 터미널 창에서 Android Studio 프로젝트 루트로 이동하고 다음을 실행합니다.

amplify init

각 항목에 대해 다음을 입력하십시오.

  • 기본 편집기를 선택: Visual Studio 코드(또는 좋아하는 편집기)
  • android처럼 제작 중인 앱 유형을 선택하십시오.
  • Res 디렉토리의 위치: (app/src/main/res): 기본값을 사용하려면 Enter를 누릅니다.
  • AWS 프로파일을 사용하시겠습니까? .
  • 사용할 프로파일을 선택: 기본값

AWS CloudFormation은 앱을 지원하는 초기 인프라입니다. 작업이 완료되면 AWS Amplify CLI 도구 체인이 새 프로젝트를 초기화하고 앱의 프로젝트 디렉토리에 amplify.amplifyrc와 같은 몇 가지 새로운 파일과 폴더가 표시됩니다. 이 파일은 프로젝트의 구성을 유지합니다.

GraphQL API 추가, 인증 추가 및 클라이언트 코드 생성

AWS Amplify 도구 체인은 API를 만들고, 인증을 추가하고, 클라이언트 코드를 생성하는 능률적인 프로세스를 제공합니다. 먼저 앱의 루트 디렉터리에서 다음 명령을 실행해 봅시다.

amplify add api

각 항목에 대해 다음을 입력하십시오.

  • 위에서 언급한 서비스 중 하나를 선택: GraphQL
  • API 이름을 입력: AmplifyAndroid
  • API의 인증 유형을 선택: Amazon Cognito User Pool
  • 기본 인증 및 보안 구성을 사용하시겠습니까? 예, 기본 구성을 사용합니다.
  • 주석이 달린 GraphQL 스키마가 있습니까? 아니요.
  • 가이드 스키마 생성을 원하십니까? .
  • 프로젝트를 가장 잘 설명하는 형태는 다음과 같습니다. (예 : ID, 이름, 설명이 포함된 “Todo”)
  • 지금 스키마를 편집하시겠습니까? (네/아니요) .

메시지가 나타나면 스키마를 다음으로 업데이트합니다.

type Pet @model {
  id: ID!
  name: String!
  description: String
}

터미널로 돌아가서 Enter를 눌러 계속 진행합니다.

이제 다음을 실행하여 구성을 AWS 계정으로 푸시보겠습니다.

amplify push

추가된 변경 사항을 묻는 메시지가 나타납니다.

| Category | Resource name          | Operation | Provider plugin   |
| -------- | ---------------------- | --------- | ----------------- |
| Auth     | cognito12345678        | Create    | awscloudformation |
| Api      | AmplifyAndroidWorkshop | Create    | awscloudformation |
  • 정말 계속 하시겠습니까? (네/아니요) .

이제 새로운 API를 위한 코드를 생성하라는 메시지가 표시됩니다.

  • 새로 생성 된 GraphQL API에 대한 코드 생성 여부(네/아니요) .
  • 쿼리, 변형 및 구독으로 이뤄진 파일 이름 패턴을 입력하십시오(app/src/main/graphql/**/*.graphql): 기본값을 그대로 사용하려면 Enter를 누릅니다.
  • 가능한 모든 GraphQL 연산(쿼리, 변형 및 구독)의 생성 및 업데이트 여부(네/아니요) .

AWS CloudFormation이 재실행되어 새로 생성된 API 및 인증 메커니즘을 AWS 계정으로 업데이트합니다. 이 프로세스에는 몇 분이 소요될 수 있습니다.

생성된 새 AWS AppSync API를 보려면 언제든지 https://console.aws.amazon.com/appsync의 대시보드로 이동하십시오. 또한 AWS 리전이 올바르게 설정되었는지 확인하십시오.

생성된 새로운 Amazon Cognito 사용자 인증을 보려면 언제든지 https://console.aws.amazon.com/cognito/의 대시보드로 이동하십시오. 또한 AWS 리전이 올바르게 설정되었는지 확인하십시오.

AWS CloudFormation이 클라우드의 리소스 업데이트를 완료하면 GraphQL API 엔드포인트가 생성되고 생성된 GraphQL 문을 프로젝트에서 사용할 수 있습니다.

API가 투명하고 API를 곧바로 사용할 수는 있지만 app/src/main/graphql/com/amazonaws/amplify/generated/graphql하의 Android Studio에서 새로 생성된 GraphQL 쿼리, 변형 구독을 검토할 수 있습니다.

Android 앱 제작

백엔드는 준비되었습니다. 이제 Android 앱에서 사용해 봅시다.

시작하기 전에 자동 가져오기 기능을 켜야 합니다. 많은 라이브러리를 사용 중입니다! 이를 위해서는 Preferences -> Editor -> General -> Auto import를 여십시오. 그런 다음 즉시 명확한 가져오기 추가를 선택하십시오.

프로젝트를 제작하고 실행하여 클라이언트 코드 생성 프로세스를 시작하십시오. 이 gradle 빌드 프로세스는 즉시 사용할 수 있는 모든 네이티브 객체 유형을 만듭니다. 다음 스크린샷과 같이 빈 앱을 볼 수 있어야 합니다.

궁금한 점이 있으면 프로젝트 보기로 전환하고 app/build/generated/source/appsync/com/amazonaws/amplify/generated/graphql/을 검색하여 생성된 모든 객체 유형, 쿼리, 변형 및 구독 Java 클래스를 검사합니다.

인증 추가

앞서 인증을 위해 Amazon Cognito 사용자 풀을 사용하도록 앱을 구성 했으므로 인증을 앱에 통합해야 합니다. 작업 편의를 고려해 Amazon Cognito 인증을 위해 AWS Mobile 라이브러리에 내장된 로그인 UI를 활용할 것입니다.

앱의 build.gradle을 열고 다음과 같은 종속성을 추가합니다.

// Mobile Client for initializing the SDK   
implementation('com.amazonaws:aws-android-sdk-mobile-client:2.8.+@aar') { transitive = true }     
// Cognito UserPools for SignIn    
implementation('com.amazonaws:aws-android-sdk-auth-userpools:2.8.+@aar') { transitive = true }     
// Sign in UI Library    
implementation('com.amazonaws:aws-android-sdk-auth-ui:2.8.+@aar') { transitive = true }

앱 디렉터리를 마우스 오른쪽 버튼으로 클릭하고 New -> Activity -> Empty Activity를 선택합니다. AuthenticationActivity 활동의 이름을 지정하고 Launcher Activity 확인란을 선택한 다음 Finish을 클릭합니다.

AuthenticationActivity.java 클래스에서 클래스를 다음과 같이 수정하십시오.

public class AuthenticationActivity extends AppCompatActivity {

    private final String TAG = AuthenticationActivity.class.getSimpleName();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_authentication);

        AWSMobileClient.getInstance().initialize(getApplicationContext(), new Callback<UserStateDetails>() {

            @Override
            public void onResult(UserStateDetails userStateDetails) {
                Log.i(TAG, userStateDetails.getUserState().toString());
                switch (userStateDetails.getUserState()){
                    case SIGNED_IN:
                        Intent i = new Intent(AuthenticationActivity.this, MainActivity.class);
                        startActivity(i);
                        break;
                    case SIGNED_OUT:
                        showSignIn();
                        break;
                    default:
                        AWSMobileClient.getInstance().signOut();
                        showSignIn();
                        break;
                }
            }

            @Override
            public void onError(Exception e) {
                Log.e(TAG, e.toString());
            }
        });
    }

    private void showSignIn() {
        try {
            AWSMobileClient.getInstance().showSignIn(this,
                 SignInUIOptions.builder().nextActivity(MainActivity.class).build());
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    }
}

이제 AuthenticationActivity가 우리의 시작 관리자 활동인지 확인해 봅시다. AndroidManifest.xml을 열고 AuthenticationActivity에 대해 <intent-filter> 블록이 다음과 같이 지정되었는지 확인하십시오. MainActivity를 위해 <intent-filter>android:theme을 제거해야 합니다.

<!-- ... Other Code... -->
<activity
    android:name=".MainActivity"
    android:label="@string/app_name">
</activity>
<activity
    android:name=".AuthenticationActivity"
    android:noHistory="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

마지막으로 activity_main.xmlMainActivity.java를 수정하고 AppBarLayout과 관련된 코드를 삭제하여 다음과 같이 구성해 보겠습니다.

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    tools:context=".MainActivity">

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     }
}

에뮬레이터에서 앱을 제작하고 시작하십시오. 로그인 UI는 다음과 같이 표시될 것입니다.

이제 사용자를 추가하겠습니다. 에뮬레이터에서 Create New Account를 선택합니다. 사용자 이름을 입력하고 복잡한 비밀번호를 선택하십시오. 암호는 8자 이상이어야 하며 대문자, 소문자, 특수 문자 및 숫자를 포함 할 수 있습니다. 유효한 이메일을 입력하면 인증 코드를 받을 수 있습니다.

Sign Up을 선택합니다.

"cognito-idp.us-east-1.amazonaws.com" 호스트를 확인할 수 없음과 같은 오류가 표시되면 에뮬레이터가 인터넷에 연결되어 있는지 다시 확인하십시오. 필요한 경우 에뮬레이터를 다시 시작하십시오.

확인 코드가 지정된 이메일의 받은 편지함에 곧 도착할 것입니다. 해당 코드를 다음 화면에 입력하고 Confirm을 선택하여 가입 절차를 완료하십시오.

성공적으로 로그인하면 성공적인 메시지가 표시되고 MainActivity인 동일한 빈 화면으로 다시 이동해야 합니다.

 

Amazon Cognito 사용자 풀에서 생성된 새 사용자를 보려면 https://console.aws.amazon.com/cognito/의 대시보드로 돌아가십시오. 또한 AWS 리전이 올바르게 설정되었는지 확인하십시오.

AWS AppSync 클라이언트 생성

이제 API 호출을 수행하기 위해 AWSAppSyncClient를 생성해야 합니다. 패키지에 새로운 ClientFactory.java 클래스를 추가하십시오.

public class ClientFactory {
    private static volatile AWSAppSyncClient client;

    public static synchronized void init(final Context context) {
        if (client == null) {
            final AWSConfiguration awsConfiguration = new AWSConfiguration(context);
            client = AWSAppSyncClient.builder()
                     .context(context)
                     .awsConfiguration(awsConfiguration)
                     .cognitoUserPoolsAuthProvider(new CognitoUserPoolsAuthProvider() {
                        @Override
                        public String getLatestAuthToken() {
                            try {
                                return AWSMobileClient.getInstance().getTokens().getIdToken().getTokenString();
                            } catch (Exception e){
                                Log.e("APPSYNC_ERROR", e.getLocalizedMessage());
                                return e.getLocalizedMessage();
                            }
                         }
                     }).build();
         }
    }

    public static synchronized AWSAppSyncClient appSyncClient() {
        return client;
    }
}

ClientFactory 클래스는 데이터 액세스 활동을 수행하는 데 사용할 수 있는 AppSync 클라이언트를 제공합니다.

데이터 쿼리

아직 목록에 아무런 데이터도 없지만 데이터가 있을 때 데이터를 표시 할 수 있는 기능을 구축합시다.

RecyclerView를 추가하여 항목 목록 표시

이제 항목을 표시할 수 있도록 앱을 제작해 봅시다.

우리는 RecyclerView를 사용하여 데이터를 표시합니다. src/res/layout/content_main.xml을 열고 텍스트 보기로 전환한 다음 <TextView>를 다음 내용으로 바꿉니다.

<android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

이제 목록에 있는 각 항목의 모양을 정의해 보겠습니다. res/layout 폴더를 마우스 오른쪽 버튼으로 클릭하고 새로운 Layout 리소스 파일을 추가합니다. 파일 이름을 recyclerview_row.xml로 합니다. Root elementLinearLayout으로 변경하고 나머지는 기본값으로 유지한 다음 OK를 선택하십시오.

recyclerview_row.xml텍스트 보기로 전환하고 레이아웃을 다음과 같이 수정합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:paddingLeft="10dp"
        android:textSize="15dp"
        android:id="@+id/txt_name"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:paddingLeft="10dp"
        android:textSize="15dp"
        android:id="@+id/txt_description"
        />

</LinearLayout>

RecyclerView를 사용하기 때문에 이를 위해 어댑터를 제공해야 합니다. 새로운 Java 클래스 MyAdapter.java를 추가하십시오. 이는 RecyclerView.Adapter를 확장합니다.

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private List<ListPetsQuery.Item> mData = new ArrayList<>();;
    private LayoutInflater mInflater;


    // data is passed into the constructor
    MyAdapter(Context context) {
        this.mInflater = LayoutInflater.from(context);
    }

    // inflates the row layout from xml when needed
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.recyclerview_row, parent, false);
        return new ViewHolder(view);
    }

    // binds the data to the TextView in each row
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bindData(mData.get(position));
    }

    // total number of rows
    @Override
    public int getItemCount() {
        return mData.size();
    }

    // resets the list with a new set of data
    public void setItems(List<ListPetsQuery.Item> items) {
        mData = items;
    }

    // stores and recycles views as they are scrolled off screen
    class ViewHolder extends RecyclerView.ViewHolder {
        TextView txt_name;
        TextView txt_description;

        ViewHolder(View itemView) {
            super(itemView);
            txt_name = itemView.findViewById(R.id.txt_name);
            txt_description = itemView.findViewById(R.id.txt_description);
        }

        void bindData(ListPetsQuery.Item item) {
            txt_name.setText(item.name());
            txt_description.setText(item.description());
        }
    }
}

클래스 수준 변수mData에 주의하십시오. 이는 ListPetsQuery.Item 유형의 목록입니다.이 목록은 스키마를 기반으로 생성된 GraphQL 유형입니다.

또한 우리는 데이터 세트의 외부 재설정을 허용하기 위해 setItems 메서드를 표시했습니다.

RecyclerView를 채우는 화면 만들기

MainActivity.java를 열고 클래스를 수정하여 쿼리 메서드를 구현하고 RecyclerView를 채웁니다.

public class MainActivity extends AppCompatActivity {

    RecyclerView mRecyclerView;
    MyAdapter mAdapter;

    private ArrayList<ListPetsQuery.Item> mPets;
    private final String TAG = MainActivity.class.getSimpleName();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRecyclerView = findViewById(R.id.recycler_view);

        // use a linear layout manager
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

        // specify an adapter (see also next example)
        mAdapter = new MyAdapter(this);
        mRecyclerView.setAdapter(mAdapter);

        ClientFactory.init(this);
    }

    @Override
    public void onResume() {
        super.onResume();

        // Query list data when we return to the screen
        query();
    }

    public void query(){
        ClientFactory.appSyncClient().query(ListPetsQuery.builder().build())
                .responseFetcher(AppSyncResponseFetchers.CACHE_AND_NETWORK)
                .enqueue(queryCallback);
    }

    private GraphQLCall.Callback<ListPetsQuery.Data> queryCallback = new GraphQLCall.Callback<ListPetsQuery.Data>() {
        @Override
        public void onResponse(@Nonnull Response<ListPetsQuery.Data> response) {

            mPets = new ArrayList<>(response.data().listPets().items());

            Log.i(TAG, "Retrieved list items: " + mPets.toString());

            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mAdapter.setItems(mPets);
                    mAdapter.notifyDataSetChanged();
                }
            });
        }

        @Override
        public void onFailure(@Nonnull ApolloException e) {
            Log.e(TAG, e.toString());
        }
    };
}

appSyncClient는 AWS AppSync GraphQL 엔드포인트를 쿼리하는 작업을 수행합니다. 최신 데이터를 얻기 위해 네트워크에 접속하는 동안 로컬 캐시의 데이터를 먼저 검색하기 때문에 CACHE_AND_NETWORK 모드를 사용하기로 했습니다. 가져오기가 완료되면 queryCallback이 다시 호출되고 데이터 세트가 최신 데이터로 업데이트됩니다. 앱 데이터 가져오기 요구에 따라 사용할 수 있는 다른 캐시 또는 네트워크 전용/첫 번째 모드가 있습니다.

앱을 다시 제작하여 오류가 없는지 확인합니다. 여전히 빈 화면이 표시되지만 Logcat 창에서 로그를 볼 수 있을 것입니다. 이는 다음과 비슷한 쿼리가 성공적으로 완료되었음을 의미합니다.

09-28 10:32:16.789 11605-11699/com.example.demo.mypetapp I/MainActivity: Retrieved list items: []

애완 동물 추가

이제 애완 동물을 추가하는 기능을 추가해 보겠습니다.

New -> Activity -> Empty Activity를 선택하여 새로운 Empty Activity을 추가하십시오. 활동의 이름을 AddPetActivity로 지정한 다음 Finish을 선택하십시오.

레이아웃 파일 activity_add_pet.xml을 열고 기존 <android.support.constraint.ConstraintLayout> 내에 다음 레이아웃을 추가하십시오.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_margin="15dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Name"
        android:textSize="15sp"
        />
    <EditText
        android:id="@+id/editTxt_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Description"
        android:textSize="15sp" />
    <EditText
        android:id="@+id/editText_description"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_save"
        android:layout_marginTop="15dp"
        android:text="Save"/>
</LinearLayout>

이는 애완 동물의 이름과 설명에 대한 기본 입력 필드를 제공합니다.

AddPetActivity.java를 열고 다음 코드를 추가하여 텍스트 입력값을 읽습니다. 새 애완 동물을 추가하는 새로운 변형을 만듭니다.

public class AddPetActivity extends AppCompatActivity {
    private static final String TAG = AddPetActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_pet);

        Button btnAddItem = findViewById(R.id.btn_save);
        btnAddItem.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                save();
            }
        });
    }

    private void save() {
        final String name = ((EditText) findViewById(R.id.editTxt_name)).getText().toString();
        final String description = ((EditText) findViewById(R.id.editText_description)).getText().toString();

        CreatePetInput input = CreatePetInput.builder()
                .name(name)
                .description(description)
                .build();

        CreatePetMutation addPetMutation = CreatePetMutation.builder()
                .input(input)
                .build();
        ClientFactory.appSyncClient().mutate(addPetMutation).enqueue(mutateCallback);
    }

    // Mutation callback code
    private GraphQLCall.Callback<CreatePetMutation.Data> mutateCallback = new GraphQLCall.Callback<CreatePetMutation.Data>() {
        @Override
        public void onResponse(@Nonnull final Response<CreatePetMutation.Data> response) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(AddPetActivity.this, "Added pet", Toast.LENGTH_SHORT).show();
                    AddPetActivity.this.finish();
                }
            });
        }

        @Override
        public void onFailure(@Nonnull final ApolloException e) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Log.e("", "Failed to perform AddPetMutation", e);
                    Toast.makeText(AddPetActivity.this, "Failed to add pet", Toast.LENGTH_SHORT).show();
                    AddPetActivity.this.finish();
                }
            });
        }
    };
}

이제 우리의 AddPetActivityMainActivity에 연결합시다.

레이아웃 파일 activity_main.xml을 열고 RecyclerView 다음의 부동 버튼을 다음으로 바꿉니다.

<android.support.design.widget.FloatingActionButton
        android:id="@+id/btn_addPet"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|right|end"
        android:layout_margin="16dp"
        android:tint="@android:color/white"
        app:srcCompat="@android:drawable/ic_input_add"/>

MainActivity.java를 다시 열고, addPetbutton을 눌렀을 때 AddPetActivity를 시작하기 위해 onCreate의 기존 코드를 수정합니다.

protected void onCreate(Bundle savedInstanceState) {
    //... Other code....

    FloatingActionButton btnAddPet = findViewById(R.id.btn_addPet);
      btnAddPet.setOnClickListener(new View.OnClickListener() {

          @Override
          public void onClick(View view) {
              Intent addPetIntent = new Intent(MainActivity.this, AddPetActivity.class);
              MainActivity.this.startActivity(addPetIntent);
          }
    });
}

이제 프로젝트를 빌드하고 시작한 다음, 추가 기능을 테스트해 봅시다.

메시지가 다시 표시되면 이전에 생성한 사용자 이름과 암호로 로그인하십시오. 그런 다음 빈 화면에서 “+” 버튼을 선택하십시오.

이름과 설명을 입력하라는 화면이 나타날 것입니다. 아래에 몇 가지 테스트 값을 입력하여 첫 번째 애완 동물을 추가하십시오.

Save를 선택하여 변형을 보내 애완 동물을 만듭니다. 생성 작업은 성공적으로 수행되어야 하며 목록에는 처음 생성된 항목이 표시되어야 합니다. 이전에 onResume()에서 “다시 가져오기”를 지정했기 때문에 가장 최신 데이터를 갖게 됩니다.

이제 애완 동물의 목록을 보여주고 애완 동물을 추가할 수 있는 Android 앱을 만들었습니다.

의견 보내기

이제 다음 단계는 블로그 시리즈의 2부를 살펴 보세요. Android 앱에 오프라인 지원, 실시간 구독 및 객체 저장소를 추가 할 수 있게 될 것입니다. 더 자세한 것은 AWS Amplify 웹 사이트에서 AWS Amplify에서 살펴 볼 수 있습니다.

– Channy (윤석찬);

혹시 만약 React를 사용하여 사용자들이 사진을 업로드하고 공유하는 data-driven 기반의 안전한 사진 갤러리 웹 애플리케이션 개발을 하고자 하신다면 단계별 실습 과정을 살펴 보시기 바랍니다.