[Android Studio] 게시글 읽기 페이지 구현(CRUD->R) - Kotlin

2024. 10. 13. 19:05·모바일 앱개발(Kotlin-PHP-Mysql)

안녕하십니까! 저번 포스팅에선 DB에서 게시글 정보를 가져온 후 리사이클뷰로 띄우는 작업을 하였습니다. 이번 포스팅은 저번 '게시판 기능 구현' 포스팅에 이어서 글을 클릭하였을 때 게시글을 읽을 수 있는 기능을 구현해 보겠습니다! 

 

'게시판 기능 구현 포스팅'

 

[Android Studio] 게시판 기능 구현 + 리사이클 뷰 생성 (Kotlin)

안녕하십니까! 저번 회원가입 기능에 이어서 게시판 기능을 구현해 보겠습니다. 게시판은 리사이클 뷰를 사용하여 구현을 했으며 인스타그램처럼 편하게 내리면서 볼 수 있게 구현해 보았습니

jamesbexter.tistory.com


<완성본 미리보기>

 

게시판에서 게시글 클릭 게시글 읽기 페이지

<1. acivitiy_read.xml>

 

> 우선 읽기 페이지는 다음과 같이 디자인해주었습니다.

↑ 읽기 페이지 UI

 

↓ 읽기 페이지 코드

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/post_read_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#3C3A3A"
    tools:context=".ReadActivity">

    <ImageButton
        android:id="@+id/btn_back2"
        android:layout_width="60dp"
        android:layout_height="48dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="23dp"
        android:contentDescription="back button"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="?attr/actionModeCloseDrawable" />

    <TextView
        android:id="@+id/post_content"
        android:layout_width="321dp"
        android:layout_height="450dp"
        android:layout_marginTop="-80dp"
        android:background="#E9DADA"
        android:gravity="center"
        android:text="게시글 내용입니다"
        android:textColor="#000000"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/post_title"
        app:layout_constraintVertical_bias="0.501" />

    <TextView
        android:id="@+id/post_title"
        android:layout_width="321dp"
        android:layout_height="63dp"
        android:layout_marginTop="100dp"
        android:background="#E9DADA"
        android:gravity="center"
        android:text="제목입니다"
        android:textColor="#000000"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 


<2. post_read.php 코드>

> 리사이클 뷰에서 게시글 클릭 시 DB에서 게시글 정보를 불러올 PHP 코드입니다.

<?php
include 'dbcon.php';


//subpage.php
session_start();
session_cache_expire(60);// 세션 유지시간 1시간

$inputJSON = file_get_contents('php://input');
$input = json_decode($inputJSON, TRUE); // Json 형식에서 배열로 디코딩 ,$_POST를 사용할 수 없기 때문에 이것을 사용.

$idx = $input['idx'] ?? NULL;   //입력값이 없으면 빈 문자열로 처리

$sql = "SELECT * FROM post_info WHERE idx=$idx";
$result = mysqli_query($db, $sql);

$posts = []; //게시글 정보를 담을 배열 생성

$posting = mysqli_fetch_assoc($result);

if ($posting) {
    $posts[] = [    //게시글 정보를 담은 배열
        'title' => $posting['post_title'],
        'writer' => $posting['post_writer'],
        'gender' => $posting['gender'],
        'date' => $posting['post_date'],
        'idx' => $posting['idx'],
        'content' => $posting['content']
    ];
    echo json_encode(['status' => 'success', 'posts' => $posts]);
} else {
    echo json_encode(['status' => 'error', 'message' => '잘못된 접근입니다.']);
}


?>

<3. ReadActivity 코드>

> 핵심이 되는 ReadActivity 코드입니다.

package com.example.test_app

import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.example.test_app.databinding.ActivityReadBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject
import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL

class ReadActivity : AppCompatActivity() {

    private var mBinding: ActivityReadBinding? = null   //mBinding이 null을 가질수 있다.
    private val binding get() = mBinding!!  //!! 를 붙여줌으로써 null 이 아니라는것을 보장.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_read)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.post_read_layout)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        mBinding = ActivityReadBinding.inflate(layoutInflater)  //xml파일과 액티비티 연결
        setContentView(binding.root)    // xml의 부모 바인딩을 가져온다.
        Log.d("post_idx: ", intent.getIntExtra("idx",-1).toString())    //게시글의 인덱스값을 가져온다.
        val idx:Int =intent.getIntExtra("idx",-1)

        CoroutineScope(Dispatchers.IO).launch {
            val postinfo: ArrayList<Post> = sendPostRequest_read(idx).second //post요청은 IO스레드에서

            withContext(Dispatchers.Main) { //UI 업데이트는 Main단에서
                binding.postTitle.setText(postinfo.get(0).title)
                binding.postContent.setText(postinfo.get(0).content)

                binding.btnBack2.setOnClickListener {   //뒤로가기 버튼
                    super.onBackPressed() //뒤로가기 기능
                }
            }
        }
    }

    // 서버로 HTTP 요청을 보내는 함수
    private fun sendPostRequest_read(idx: Int): Pair<Int,ArrayList<Post>> {  //인덱스에 해당하는 게시물 1개만 가져오는 함수
        val url = URL("http://192.168.0.10/post_read.php")
        val postData = JSONObject()
        postData.put("idx", idx)      //json 형식으로 보낸다는것을 주의!! php 에서 $_POST로는 사용불가!

        val result = with(url.openConnection() as HttpURLConnection) {
            requestMethod = "POST"
            doOutput = true

            val outputStream = BufferedOutputStream(outputStream)
            BufferedWriter(OutputStreamWriter(outputStream, "UTF-8")).use { writer ->
                writer.write(postData.toString())
                writer.flush()
            }


            //url로 데이터 전송후 서버로부터 응답을받는 부분
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader(InputStreamReader(inputStream)).use { reader ->
                    val response = StringBuilder()  //동적문자열객체 선언(이로인해 이 문자열 뒤로 계속 추가해나갈수있음)이자체로는 문자열이 아님!
                    var line: String?
                    while (reader.readLine().also { line = it } != null) {
                        response.append(line)   //json 응답을 문자열로 가져옴
                    }

                    //JSON 응답을 처리
                    val jsonResponse= JSONObject(response.toString())//응답을 다시 json객체로 변환
                    val status=jsonResponse.getString("status")//응답에서 key=status 인 데이터 저장
                    val postArray=jsonResponse.getJSONArray("posts")//응답에서 posts라는 이름의 배열 저장

                    //게시글 정보를 List로 변환 <PostAdapter와의 호환을 위하여 변환해야함>
                    val postList= ArrayList<Post>() //Post형식의 배열을 가진 동적List 생성

                    for (i in 0 until 1){
                        val postJson=postArray.getJSONObject(0)//i번째 게시글 정보를 가져온다.
                        val post= Post(
                            title=postJson.getString("title"),
                            writer=postJson.getString("writer"),
                            gender = postJson.getInt("gender"),
                            date = postJson.getString("date"),
                            idx=postJson.getInt("idx"),
                            content = postJson.getString("content")
                        )
                        //Post 객체 생성 후 리스트에 추가
                        postList.add(post)
                    }

                    Log.d("HTTP_POST", "Response: $response")   // 결과값 Logcat 으로 확인가능!
                    return@with Pair(1,postList)
                }
            } else {
                Log.e("HTTP_POST", "Error: $responseCode")  //에러발생시 에러코드 출력!
                return@with Pair(0, ArrayList<Post>())
            }
        }
        return result
    }
}

 

1. sendPostRequest_Read 함수

> DB에서 게시글 정보를 가져온 PHP파일에 출력된 내용을 Kotlin으로 가져오는 함수입니다.

 

2. 게시글의 idx 값은 어떻게 가져온건가요?

위에 달아드린 링크 속 글에서 설명했지만 리사이클 뷰를 위해서 list_post.xml 이란 파일을 만들었습니다. xml 요소 중 post_idx 란 textview를 만들고 안 보이게끔 처리해 주었습니다. 게시글 클릭 시 textview에 저장되어 있던 idx값 을 intent.putExtra("idx",post.idx) 를 이용하여 게시글 읽기 페이지로 넘어가면서 idx도 같이 넘겨주었습니다.


긴 글 읽어주셔서 감사합니다!

'모바일 앱개발(Kotlin-PHP-Mysql)' 카테고리의 다른 글

[Android Studio] PHP 서버와 통신시 세션ID 활용하는 방법 -Kotlin  (0) 2024.10.17
[Android Studio] 게시글 CRUD(생성,읽기,수정,삭제)기능 구현 -Kotlin  (0) 2024.10.15
[Android Studio] 게시판 기능 구현 + 리사이클 뷰 생성 (Kotlin)  (0) 2024.10.11
[Android Studio] 무선 디버깅 연결이 안될때 수동으로 연결하는법.  (0) 2024.10.07
[Android Studio] 회원가입 기능 구현 - Kotlin  (1) 2024.10.05
'모바일 앱개발(Kotlin-PHP-Mysql)' 카테고리의 다른 글
  • [Android Studio] PHP 서버와 통신시 세션ID 활용하는 방법 -Kotlin
  • [Android Studio] 게시글 CRUD(생성,읽기,수정,삭제)기능 구현 -Kotlin
  • [Android Studio] 게시판 기능 구현 + 리사이클 뷰 생성 (Kotlin)
  • [Android Studio] 무선 디버깅 연결이 안될때 수동으로 연결하는법.
무너박사
무너박사
IT 보안 블로그 입니다. 제가 작성하는 블로그가 누군가의 공부에 조금이라도 도움이 되길 바라며 작성하였습니다.
  • 무너박사
    무너박사의 연구일지
    무너박사
  • 전체
    오늘
    어제
    • 분류 전체보기 (104)
      • WEB 지식 (3)
      • 웹해킹 (13)
      • 웹개발(PHP-Mysql) (12)
      • 웹개발(JSP-Oracle) (2)
      • 워게임 문제풀이 (19)
        • Segfault (17)
        • Dreamhack (2)
      • SQL (3)
      • Python (2)
      • AI (1)
        • LLM(Large Language Model) (1)
      • Kail Linux (3)
      • 잡다한 지식 (2)
      • 모바일 앱개발(Kotlin-PHP-Mysql) (13)
      • 모바일 앱해킹(Android) (31)
        • Frida Lab (2)
        • Android DIVA (8)
        • Insecure Bank (20)
      • 안드로이드 위협 탐지 및 우회 (0)
        • 루팅 탐지 & 우회 (0)
        • 디버깅 탐지 & 우회 (0)
        • 에뮬레이터 탐지 & 우회 (0)
        • Frida 탐지 & 우회 (0)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      php
      웹해킹
      insecure bank
      모바일 앱개발
      Koltin
      Android Studio
      sql injection
      android diva
      normaltic
      Kotlin
      인시큐어 뱅크
      XSS
      취업반 6기
      모바일앱개발
      취업반6기
      모바일 앱해킹
      취업반
      시스템해킹
      칼리리눅스
      Blind sql injection
      dom based xss
      mobile diva
      리패키징
      인시큐어뱅크
      모의해킹
      안드로이드 스튜디오
      MySQL
      해킹
      앱해킹
      워게임
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    무너박사
    [Android Studio] 게시글 읽기 페이지 구현(CRUD->R) - Kotlin
    상단으로

    티스토리툴바