자세히…
[Android, Kotlin] BottomNavigation
1. 기능 구현 화면 하단에 BottomNavigation 를 만들어보자. (like. Instagram) Navigation 메뉴에 따라 화면(Fragment)를 변경해보자. 2. Android Studio에서 기본 프로젝트(with empty activity) 생성하자! 생성시 'Empty Activity'로 기본 생성 3. ViewBinding 사용을 위한 build.gradle 설정 android { // 뷰 바인딩 옵션 활성화 viewBinding { enabled = true } } 4. BottomNavigation 아이콘 만들기 (Vertor Asset-기본 제공) res -> drawable 우클릭 -> New -> Vector Asset Clip Art -> Select ..

자세히…
- 핸드폰 권한 설정
- xml, kt 구현
Code1 : 기본 사진 접근 코드
- AndroidManifest에서 추가해야 할 것
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
- Main xml
package com.example.photo_book import android.app.Activity import android.content.Intent import android.os.Bundle import android.widget.Button import android.widget.ImageView class MainActivity : Activity() { private val PICK_IMAGE = 1 private lateinit var imageView: ImageView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) imageView = findViewById(R.id.imageView) val pickImageButton: Button = findViewById(R.id.pick_image_button) pickImageButton.setOnClickListener { val intent = Intent(Intent.ACTION_PICK) intent.type = "image/*" startActivityForResult(intent, PICK_IMAGE) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PICK_IMAGE && resultCode == RESULT_OK) { data?.data?.let { imageUri -> imageView.setImageURI(imageUri) } } } }
- Main kt
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/pick_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Pick Image" android:layout_centerInParent="true"/> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/pick_image_button" android:layout_marginTop="16dp" android:src="@drawable/ic_launcher_foreground" android:layout_centerHorizontal="true"/> </RelativeLayout>
Code2 : 사진 접근 + GridView에서 사진 저장하기
- frag2 kt
package com.example.project1 import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.Button import android.widget.GridView import android.widget.ImageView @Suppress("DEPRECATION") class Frag2 : Fragment() { // frag2 class 정의 및 Fragment class 상속 private val PICK_IMAGE_REQUEST = 1 // 이미지 선택 알리는 토글 변수 private lateinit var gridView: GridView private lateinit var myGridAdapter: MyGridAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_frag2, container, false) gridView = view.findViewById(R.id.gridView) myGridAdapter = MyGridAdapter(requireContext()) gridView.adapter = myGridAdapter val selectImageButton = view.findViewById<Button>(R.id.select_image_button) selectImageButton.setOnClickListener { openGallery() } return view } private fun openGallery() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent, PICK_IMAGE_REQUEST) } @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK && data != null) { val selectedImageUri = data.data if (selectedImageUri != null) { myGridAdapter.addImage(selectedImageUri) } } } inner class MyGridAdapter(private val context: Context) : BaseAdapter() { private val imageUris = ArrayList<Uri>() override fun getCount(): Int { return imageUris.size } override fun getItem(position: Int): Any { return imageUris[position] } override fun getItemId(position: Int): Long { return position.toLong() } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val imageView = convertView as? ImageView ?: ImageView(context).apply { layoutParams = ViewGroup.LayoutParams(200, 200) scaleType = ImageView.ScaleType.FIT_CENTER setPadding(5, 5, 5, 5) } val imageUri = getItem(position) as Uri imageView.setImageURI(imageUri) return imageView } fun addImage(uri: Uri) { imageUris.add(uri) notifyDataSetChanged() } } }
- Main xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center|bottom" android:layout_marginBottom="140dp"> <!-- 버튼을 먼저 정의 --> <Button android:id="@+id/select_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@string/select_image" /> <!-- 그리드뷰를 버튼 아래에 배치 --> <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="40dp" android:layout_below="@id/select_image_button" android:layout_marginTop="-458dp" android:gravity="top" android:numColumns="5" /> <!-- 추가적인 UI 요소들을 정의할 수 있습니다 --> </RelativeLayout>
Code3: 갤러리 advanced (삭제, 취소 등 ..)
package com.example.project1 import android.annotation.SuppressLint import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.Button import android.widget.GridView import android.widget.ImageView import androidx.appcompat.app.AlertDialog // 각종 위젯 불러오기 @Suppress("DEPRECATION") // 그냥 경고 메세지를 무시하는 annotation이라고 한다. class Frag2 : Fragment() { // frag2 class 이다. fragment를 상속 받는다. private val PICK_IMAGE_REQUEST = 1 // 이미지 클릭을 알리는 toggle number private lateinit var gridView: GridView // GridView를 변수로 지정 private lateinit var myGridAdapter: MyGridAdapter // GridView에 데이터를 전달할 MyGridAdapter class를 변수로 지정 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_frag2, container, false) // inflate는 xml 파일을 view 객체로 바꾸는 과정이다. // onCreatView는 view 개체를 생성하는 과정이라고 생각하면 좋을 것 같다! gridView = view.findViewById(R.id.gridView) myGridAdapter = MyGridAdapter(requireContext()) gridView.adapter = myGridAdapter // gridview를 초기화 한다. val selectImageButton = view.findViewById<Button>(R.id.select_image_button) selectImageButton.setOnClickListener { openGallery() } // 버튼 설정 -> 버튼 리스너 (= 클릭시 갤러리 열기) return view // view 개체를 반환 한다. } private fun openGallery() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent, PICK_IMAGE_REQUEST) } // intend는 실행할 작업을 생성하는 객체 -> 여기서는 이미지 선택 요청을 보낸다. // 선택 했는지, 안했는지는 PICK_IMAGE_REQUEST 변수로 확인할 수 있다. @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK && data != null) { val selectedImageUri = data.data if (selectedImageUri != null) { myGridAdapter.addImage(selectedImageUri) } } } // 이미지가 선택당한 걸 확인하면 Grid에 이미지를 추가한다. // 아~ 이게 MyGridAdapter class이구나..!! inner class MyGridAdapter(private val context: Context) : BaseAdapter() { private val imageUris = ArrayList<Uri>() override fun getCount(): Int { return imageUris.size } override fun getItem(position: Int): Any { return imageUris[position] } override fun getItemId(position: Int): Long { return position.toLong() } // 개수, 아이템, 포지션 가져오는 함수들.. override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { // convertView는 스크롤 관리 val imageView = convertView as? ImageView ?: ImageView(context).apply { layoutParams = ViewGroup.LayoutParams(200, 200) // 정사각형으로 크기 설정 scaleType = ImageView.ScaleType.CENTER_CROP // 이미지를 ImageView에 맞게 자르기 setPadding(0, 0, 0, 0) // padding 제거 혹은 필요에 따라 조정 } val imageUri = getItem(position) as Uri imageView.setImageURI(imageUri) imageView.setOnClickListener { showImageDialog(imageUri) } // view에 있는 이미지가 선택 되었다면 image를 확대해서 보여준다. // 만약에 이미지 확대 말고 다른 action을 취할 거라면 이 부분 수정하면 될 것 같다. return imageView } fun addImage(uri: Uri) { val dialogView = LayoutInflater.from(context).inflate(R.layout.image, null) val dialogImageView = dialogView.findViewById<ImageView>(R.id.ImageView) dialogImageView.setImageURI(uri) val alertDialog = AlertDialog.Builder(context) .setView(dialogView) .setPositiveButton("Select") { dialog, _ -> // Handle Select button click if needed } .setNegativeButton("Cancel") { dialog, _ -> // Handle Cancel button click dialog.dismiss() // Dismiss the dialog } .show() // Add image URI to list only if Select button is clicked alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)?.setOnClickListener { imageUris.add(uri) notifyDataSetChanged() alertDialog.dismiss() // Dismiss the dialog after adding image URI } } // uri는 리소스를 나타내는 고유한 객체 // 다른 flagment에서는 사용할 수 없다. @SuppressLint("MissingInflatedId") private fun showImageDialog(imageUri: Uri) { val dialogView = LayoutInflater.from(context).inflate(R.layout.image, null) val dialogImageView = dialogView.findViewById<ImageView>(R.id.ImageView) dialogImageView.setImageURI(imageUri) val alertDialog = AlertDialog.Builder(context) .setView(dialogView) .setPositiveButton("Close") { dialog, _ -> dialog.dismiss() } .setNegativeButton("Delete") { dialog, _ -> // Handle Delete button click // Remove image from list and update GridView val position = imageUris.indexOf(imageUri) if (position != -1) { imageUris.removeAt(position) notifyDataSetChanged() } dialog.dismiss() } .show() } } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center|bottom" android:layout_marginBottom="140dp"> <!-- 버튼을 먼저 정의 --> <Button android:id="@+id/select_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@string/select_image" /> <!-- 그리드뷰를 버튼 아래에 배치 --> <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="400dp" android:layout_below="@id/select_image_button" android:layout_marginTop="-453dp" android:gravity="top" android:numColumns="5" /> <!-- 추가적인 UI 요소들을 정의할 수 있습니다 --> </RelativeLayout>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ImageView" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitCenter" android:adjustViewBounds="true" android:padding="16dp" android:background="@android:color/black" />
Code4: 글씨 입력, 저장 가능
// Frag2 package com.example.project1 import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.Button import android.widget.EditText import android.widget.GridView import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AlertDialog // 각종 위젯 불러오기 // @Suppress("DEPRECATION") // 그냥 경고 메세지를 무시하는 annotation이라고 한다. class Frag2 : Fragment() { private val PICK_IMAGE_REQUEST = 1 private lateinit var gridView: GridView private lateinit var myGridAdapter: MyGridAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_frag2, container, false) gridView = view.findViewById(R.id.gridView) myGridAdapter = MyGridAdapter(requireContext()) gridView.adapter = myGridAdapter val selectImageButton = view.findViewById<Button>(R.id.select_image_button) selectImageButton.setOnClickListener { openGallery() } return view } private fun openGallery() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent, PICK_IMAGE_REQUEST) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK && data != null) { val selectedImageUri = data.data if (selectedImageUri != null) { myGridAdapter.addImage(selectedImageUri) } } } data class ImageData(val imageUri: Uri, val description: String) inner class MyGridAdapter(private val context: Context) : BaseAdapter() { private val imageUris = ArrayList<Uri>() private val imageDatas = ArrayList<ImageData>() override fun getCount(): Int { return imageUris.size } override fun getItem(position: Int): Any { return imageUris[position] } override fun getItemId(position: Int): Long { return position.toLong() } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val imageView = convertView as? ImageView ?: ImageView(context).apply { layoutParams = ViewGroup.LayoutParams(200, 200) scaleType = ImageView.ScaleType.CENTER_CROP setPadding(0, 0, 0, 0) } val imageUri = getItem(position) as Uri imageView.setImageURI(imageUri) val description = imageDatas.find { it.imageUri == imageUri }?.description ?: "" imageView.setOnClickListener { showImageDialog(imageUri, description) } return imageView } fun addImage(uri: Uri) { val dialogView = LayoutInflater.from(context).inflate(R.layout.image_text_input_dialog, null) val dialogImageView = dialogView.findViewById<ImageView>(R.id.dialogImageView) val editTextDescription = dialogView.findViewById<EditText>(R.id.editTextDescription) dialogImageView.setImageURI(uri) val alertDialog = AlertDialog.Builder(context) .setView(dialogView) .setPositiveButton("Select") { dialog, _ -> val description = editTextDescription.text.toString() imageDatas.add(ImageData(uri, description)) imageUris.add(uri) notifyDataSetChanged() dialog.dismiss() } .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } .show() } private fun showImageDialog(imageUri: Uri, description: String) { val dialogView = LayoutInflater.from(context).inflate(R.layout.image_dialog, null) val dialogImageView = dialogView.findViewById<ImageView>(R.id.dialogImageView) val textViewDescription = dialogView.findViewById<TextView>(R.id.textViewDescription) dialogImageView.setImageURI(imageUri) // 이미지 설정 textViewDescription.text = description // 텍스트 설정 AlertDialog.Builder(context) .setView(dialogView) .setPositiveButton("Close") { dialog, _ -> dialog.dismiss() } .setNegativeButton("Delete") { dialog, _ -> val position = imageUris.indexOf(imageUri) if (position != -1) { imageUris.removeAt(position) imageDatas.removeAt(position) notifyDataSetChanged() } dialog.dismiss() } .show() } } }
<!--frag xml--> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center|bottom" android:layout_marginBottom="140dp"> <!-- 버튼을 먼저 정의 --> <Button android:id="@+id/select_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@string/select_image" /> <!-- 그리드뷰를 버튼 아래에 배치 --> <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="400dp" android:layout_below="@id/select_image_button" android:layout_marginTop="-453dp" android:gravity="top" android:numColumns="5" /> <!-- 추가적인 UI 요소들을 정의할 수 있습니다 --> </RelativeLayout>
<!-- image_dialog.xml --> <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="16dp"> <ImageView android:id="@+id/dialogImageView" android:layout_width="match_parent" android:layout_height="300dp" android:adjustViewBounds="true" android:scaleType="fitCenter" /> <TextView android:id="@+id/textViewDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="115dp" android:textColor="@android:color/black" android:textSize="16sp" /> </LinearLayout>
<!-- image_text_input_dialog.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <ImageView android:id="@+id/dialogImageView" android:layout_width="match_parent" android:layout_height="300dp" android:adjustViewBounds="true" android:scaleType="fitCenter" /> <EditText android:id="@+id/editTextDescription" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:hint="Enter Description" android:inputType="text" android:maxLines="1" android:paddingTop="115dp" /> </LinearLayout>
Code5: Splash

강의 01 갤러리 이미지 가져오기
MainActivity.java ``` package com.cranberryai.test; import androidx.appcompat.app.AppCompatActivit…
Code2 해석
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center|bottom" android:layout_marginBottom="140dp"> <!-- 버튼을 먼저 정의 --> <Button android:id="@+id/select_image_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:text="@string/select_image" /> <!-- 그리드뷰를 버튼 아래에 배치 --> <GridView android:id="@+id/gridView" android:layout_width="match_parent" android:layout_height="400dp" android:layout_below="@id/select_image_button" android:layout_marginTop="-453dp" android:gravity="top" android:numColumns="5" /> <!-- 추가적인 UI 요소들을 정의할 수 있습니다 --> </RelativeLayout>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ImageView" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitCenter" android:adjustViewBounds="true" android:padding="16dp" android:background="@android:color/black" />
package com.example.project1 import android.app.Activity import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.MediaStore import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.BaseAdapter import android.widget.Button import android.widget.GridView import android.widget.ImageView import androidx.appcompat.app.AlertDialog // 각종 위젯 불러오기 @Suppress("DEPRECATION") // 그냥 경고 메세지를 무시하는 annotation이라고 한다. class Frag2 : Fragment() { // frag2 class 이다. fragment를 상속 받는다. private val PICK_IMAGE_REQUEST = 1 // 이미지 클릭을 알리는 toggle number private lateinit var gridView: GridView // GridView를 변수로 지정 private lateinit var myGridAdapter: MyGridAdapter // GridView에 데이터를 전달할 MyGridAdapter class를 변수로 지정 override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_frag2, container, false) // inflate는 xml 파일을 view 객체로 바꾸는 과정이다. // onCreatView는 view 개체를 생성하는 과정이라고 생각하면 좋을 것 같다! gridView = view.findViewById(R.id.gridView) myGridAdapter = MyGridAdapter(requireContext()) gridView.adapter = myGridAdapter // gridview를 초기화 한다. val selectImageButton = view.findViewById<Button>(R.id.select_image_button) selectImageButton.setOnClickListener { openGallery() } // 버튼 설정 -> 버튼 리스너 (= 클릭시 갤러리 열기) return view // view 개체를 반환 한다. } private fun openGallery() { val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) startActivityForResult(intent, PICK_IMAGE_REQUEST) } // intend는 실행할 작업을 생성하는 객체 -> 여기서는 이미지 선택 요청을 보낸다. // 선택 했는지, 안했는지는 PICK_IMAGE_REQUEST 변수로 확인할 수 있다. @Deprecated("Deprecated in Java") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK && data != null) { val selectedImageUri = data.data if (selectedImageUri != null) { myGridAdapter.addImage(selectedImageUri) } } } // 이미지가 선택당한 걸 확인하면 Grid에 이미지를 추가한다. // 아~ 이게 MyGridAdapter class이구나..!! inner class MyGridAdapter(private val context: Context) : BaseAdapter() { private val imageUris = ArrayList<Uri>() override fun getCount(): Int { return imageUris.size } override fun getItem(position: Int): Any { return imageUris[position] } override fun getItemId(position: Int): Long { return position.toLong() } // 개수, 아이템, 포지션 가져오는 함수들.. override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { // convertView는 스크롤 관리 val imageView = convertView as? ImageView ?: ImageView(context).apply { layoutParams = ViewGroup.LayoutParams(200, 200) // 정사각형으로 크기 설정 scaleType = ImageView.ScaleType.CENTER_CROP // 이미지를 ImageView에 맞게 자르기 setPadding(0, 0, 0, 0) // padding 제거 혹은 필요에 따라 조정 } val imageUri = getItem(position) as Uri imageView.setImageURI(imageUri) imageView.setOnClickListener { showImageDialog(imageUri) } // view에 있는 이미지가 선택 되었다면 image를 확대해서 보여준다. // 만약에 이미지 확대 말고 다른 action을 취할 거라면 이 부분 수정하면 될 것 같다. return imageView } fun addImage(uri: Uri) { imageUris.add(uri) notifyDataSetChanged() } // uri는 리소스를 나타내는 고유한 객체 // 다른 flagment에서는 사용할 수 없다. private fun showImageDialog(imageUri: Uri) { val dialogView = LayoutInflater.from(context).inflate(R.layout.image, null) val dialogImageView = dialogView.findViewById<ImageView>(R.id.ImageView) dialogImageView.setImageURI(imageUri) AlertDialog.Builder(context) .setView(dialogView) .setPositiveButton("Close") { dialog, _ -> dialog.dismiss() } .show() } } }
#3.안드로이드 스튜디오 스마트폰 연결하기(개발자모드 설정)
안드로이드 스튜디오 스마트폰 연결하기 안드로이드 스튜디오에서 개발을 하고 개발한 내용을 AVD에서 확인을 해도 되지만 AVD는 간단하게 확인하는 용도이고 실제 스마트폰에 구동시켜서 테스트를 해봐야 합니다. 안드로이드 스튜디오와 스마트폰을 연결하려면 PC에 드라이버를 설치해야 합니다. 드라이버는 구글에서 '해당 제조사 드라이버'라고 검색하면 나옵니다. 저는 갤럭시로 테스트를 할 예정이라 삼성 휴대폰 드라이버를 다운로드하여 보겠습니다. 아래 URL에 접속하여 드라이버를 다운받아 설치합니다. https://developer.android.com/studio/run/oem-usb?hl=ko https://developer.samsung.com/android-usb-driver PC에 드라이버를 설치하고 나서 스..
- GridView는 자동 스크롤이 된다!
- Layout → Design → Palette를 이용하면 좀 더 쉬운 레이아웃 디자인이 가능해 진다.
Android PHP MySQL 통신(MySQL을 이용한 회원가입 예제)
이번에 경험한 것은 안드로이드 앱에서 PHP를 이용하여 MySQL(DB)에 접근해 데이터를 저장하는 방식의 회원가입을 만들어보도록 하겠습니다. [이 글의 체크 포인트] ==> 안드로이드는 바로 MySQL에 접근을 하면 되는데 굳이 왜? PHP를 거쳐서 MySQL에 접근을 할까? ◼️ 1. Android PHP MySQL 통신 방법 ◼️ 보통 안드로이드 앱에서 PHP를 이용하여 MySQL(DB)에 접근해 사용하는 방식들을 사용하고 있습니다. ==> 안드로이드는 바로 MySQL에 접근을 하면 되는데 굳이 왜? PHP를 거쳐서 MySQL에 접근을 할까? 위의 의문점이 드실 수 있습니다. 그 이유는 바로 보안상의 이유(MySQL 서버 접속용 아이디와 패스워드 유출) 때문에 '외부'데이터베이스(MySQL)에 바로..
React Native Splash Screen on Android 12
I am using react-native-splash-screen library for making my custom splash screen in the app from an image on both iOS and Android. However, Google introduced the new splash screens approach in Andr...
