본문 바로가기
안드로이드 자바

[JAVA][Android] Retrofit으로 데이터 insert하기

by teamnova 2021. 12. 11.

https://stickode.tistory.com/279  지난 포스팅 리사이클러뷰+ 레트로핏으로 데이터 불러오기 

이어서(레트로핏기본 사용법 참조)

 

이번시간에는 레트로핏을 사용해 데이터를 보내고, 서버에서  응답을 받아보겠습니다.

 

먼저 하단의 스틱코드를 즐겨찾기해주세요!

https://stickode.com/detail.html?no=2632 

 

스틱코드

 

stickode.com

 

진행순서

1.  subs 액티비티에 플로팅 버튼을 만듭니다.

2. subs 액티비티에서 플로팅 버튼을 눌러 띄울 새로운 Edit액티비티를 만듭니다.

3. Edit 액티비티에 제목과 내용을 작성합니다.(레트로핏 전송), 메뉴xml작성

4.레트로핏 API 작성

5. 인터페이스 작성

6.모델클래스작성

7.Edit 액티비티에 레스트로핏 인스턴스를 작성

8.DB에 데이터를 담을 테이블 생성

9.php insert sql 작성

10.Edit 액티비티의 우측상단의 체크버튼을 누르면 서버로 작성한 내용이 전송됩니다.

11.서버에 데이터가 전송되면 응답을 받아와, 클라이언트에서 토스트메시지를 띄워줍니다.

 

 

 

 

<subs_activity.java>

subs 액티비티에 플로팅 버튼을 만들어줍니다. 

package com.example.myapplication.Recipe_select;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.example.myapplication.Home.HomeActivity;
import com.example.myapplication.R;
import com.example.myapplication.cookStargram.CookTalkActivity;
import com.example.myapplication.mypage.MypageActivity;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.floatingactionbutton.FloatingActionButton;

import org.jetbrains.annotations.NotNull;

import java.util.List;

//액티비티생성
public class subsActivity extends AppCompatActivity {

  
    FloatingActionButton fab;

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

        /**
         *
         */
         //플로팅 버튼 
            fab = findViewById(R.id.add);
            fab.setOnClickListener(view ->
                    startActivity(new Intent(this, EditActivity.class))
            );
     

}

 

액티비티  xml

<activity_subscribe.xml>

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".Recipe_select.subscribeActivity">

   
    <!-- 플로팅 버튼-->
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_marginRight="16dp"
        android:layout_marginBottom="70dp"
        android:src="@drawable/ic_baseline_add_24"
        android:visibility="visible" />


</RelativeLayout>

 

 

플로팅 버튼을 누르면 이동할 edit 액티비티를 작성합니다.

<EditActivity.java>

제목입력란, 내용입력란이 있고 우측상단에 체크버튼이 있는 액티비티를 만듭니다.

체크버튼은 메뉴를 인플레이트해서 사용했습니다.   

메뉴버튼을 누르면 작성된내용이 서버로 전달(요청)되고, 응답을 받아옵니다.

package com.example.myapplication.Recipe_select;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Toast;

import com.example.myapplication.R;
import com.example.myapplication.mypage.RetrofitServer.ApiClient;
import com.example.myapplication.mypage.RetrofitServer.ApiInterface;

import org.jetbrains.annotations.NotNull;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class EditActivity extends AppCompatActivity {

    EditText et_title, et_note;
    ProgressDialog progressDialog;

    ApiInterface apiInterface;

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

		// 제목과 내용
        et_title = findViewById(R.id.title);
        et_note = findViewById(R.id.note);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_editer, menu);
        return true;
    }


	// 우측 상단의 체크버튼을 누르면 서버로 데이터 전송
    @SuppressLint("NonConstantResourceId")
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        switch (item.getItemId()) {
            case R.id.save:
                String title = et_title.getText().toString().trim();
                String note = et_note.getText().toString().trim();

                if (title.isEmpty()) {
                    et_title.setError("제목을 작성하세요");
                } else if (note.isEmpty()) {
                    et_note.setError("노트를 작성하세요.");
                } else {
                    saveNote(title, note);
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }

    }

   // savdNote함수 
    private void saveNote(final String title, final String note) {
		// 레트로핏으로 제목과 내용을 보냄
        apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
        Call<Note> call = apiInterface.saveNote(title, note);

        call.enqueue(new Callback<Note>() {
            @Override
            public void onResponse(@NotNull Call<Note> call, @NotNull Response<Note> response) {
        
				// 서버에서 응답을 받아옴 
                if (response.isSuccessful() && response.body() != null) {
                    Boolean success = response.body().getSuccess();
                    String message = response.body().getMessage();
				// 입력성공시 서버에서 메시지를 받아와서 토스트로 출력 
                    if (success) {
                        Toast.makeText(EditActivity.this, message, Toast.LENGTH_SHORT).show();
                        finish(); // 메인액티비티로 돌아감
                        
                         Log.e("서버에서 받아온내용", message);
                    }
                   // 응답을 받아오지 못했을경우
                } else {
                    assert response.body() != null;
                    Toast.makeText(EditActivity.this, response.body().getMessage(), Toast.LENGTH_SHORT).show();
                    finish();

                }

            }
	    // 통신실패시 
            @Override
            public void onFailure(@NonNull Call<Note> call, @NonNull Throwable t) {
                progressDialog.dismiss();
                Toast.makeText(EditActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();

            }
        });

    }
}

 

<activity.edit.xml>

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Recipe_select.EditActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginRight="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="20dp">
        
        <EditText
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="제목"
            android:textSize="24sp"
            android:inputType="textCapSentences"
            tools:ighore="Autofill"
            />


        <EditText
            android:id="@+id/note"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/title"
            android:hint="내용을 입력해주세요"
            android:gravity="top|start"
            android:textSize="24sp"
            android:layout_marginTop="20dp"
            android:minLines="6"
            android:inputType="textMultiLine"
            tools:ighore="Autofill"
            />
        
        
    </RelativeLayout>
        

</androidx.core.widget.NestedScrollView>

 

 

우측 상단 메뉴를 만들어줍니다.

res에 메뉴폴더를 생성하고, menu_editer.xml을 만듭니다.

<menu_editer.xml>

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >

    <item
        android:id="@+id/save"
        android:icon="@drawable/ic_baseline_check_24"
        android:title="저장하기"
        app:showAsAction="always" />

</menu>

 

 

레트로핏 통신을 위한 APIClient를 작성해보겠습니다.

<ApiClient.java>

package com.example.myapplication.mypage.RetrofitServer;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

// 공통으로 사용하는 APICLIENT // 레트로핏
public class ApiClient {
    private static Retrofit retrofit;
    // BaseUrl등록
    private static final String BASE_URL = "http://X.XX.XX.XXX/";

    public static Retrofit getApiClient()
    {

        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        if (retrofit == null)
        {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }

        return retrofit;
    }
}

 

Note클래스를 만듭니다.

<Note.java>

package com.example.myapplication.Recipe_select;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.io.Serializable;

// success와 , message값을 받아옵니다.
public class Note{

    @Expose
    @SerializedName("success")
    private Boolean success;
    @Expose
    @SerializedName("message")
    private String message;
    }

  
    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

 

인터페이스를 작성합니다.

 <ApiInterface.java>

package com.example.myapplication.mypage.RetrofitServer;


import com.example.myapplication.Recipe_select.Note;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;

// 인터페이스는 공통으로 사용할수 있다.
// 보내는 부분
public interface ApiInterface {

    // 노트작성내용 // 서버로 보내는값 // 제목과 내용을 보냅니다.
    @FormUrlEncoded
    @POST("save.php")
    Call<Note> saveNote(
            @Field("title") String title,
            @Field("note") String note
    );
}

 

mysqlDB에 notes라는 이름의 Table을 만듭니다.

 

 

php에 제목과 내용을 DB테이블에 넣는 쿼리를 작성합니다.

 <save.php>

제목과 내용을 받아와 notes테이블의 title, note칼럼에 insert 해줍니다.

입력이 성공하면 응답으로 "입력성공"을 보냅니다.

<?php
    // 레트로핏 노트 성공
    require_once("./dbinfo.php");

    if($_SERVER['REQUEST_METHOD']=='POST'){
        $title =$_POST['title'];
        $note =$_POST['note'];


        $query ="INSERT INTO `notes`(title, note) VALUES ('$title','$note')";

        if(mysqli_query($conn,$query)){

            $response['success']=true;
            $response['message']="입력성공";
        }else{
            $response['success']=false;
            $response['message']="Failure!";
        }


    }else{
        $response['success']=false;
        $response['message']="Error";

    }

    echo json_encode($response);

< 완성된 화면 >

서버로 전송이되면,  EditActivity가 꺼지고  "입력성공" 토스트가 생성되는것을 볼 수 있습니다.

스틱코드를 잘 활용해보세요! 

https://stickode.com/mainlogin.html

 

STICKODE

 

stickode.com