Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีส่งอีเมลพร้อมไฟล์แนบใน Android ด้วย Kotlin

ตัวอย่างนี้สาธิตวิธี ส่งอีเมลพร้อมไฟล์แนบ (Attachment) โดยใช้ Intent.ACTION_SEND และเลือกไฟล์จาก Storage ด้วย Intent.ACTION_GET_CONTENT

ขั้นตอนที่ 1: สร้างโปรเจกต์ใหม่

Android Studio → New Project → Empty Activity

ขั้นตอนที่ 2: Layout (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/etTo"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Recipient Email"
        android:inputType="textEmailAddress"
        android:layout_marginBottom="8dp" />

    <EditText
        android:id="@+id/etSubject"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Subject"
        android:layout_marginBottom="8dp" />

    <EditText
        android:id="@+id/etBody"
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:hint="Message"
        android:gravity="top|start"
        android:inputType="textMultiLine"
        android:layout_marginBottom="8dp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="8dp">

        <Button
            android:id="@+id/btnAttach"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Attach File" />

        <TextView
            android:id="@+id/tvAttachment"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_marginStart="16dp"
            android:layout_gravity="center_vertical"
            android:text="No file attached"
            android:textColor="@android:color/darker_gray" />
    </LinearLayout>

    <Button
        android:id="@+id/btnSend"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Send Email"
        android:backgroundTint="@android:color/holo_green_dark"
        android:textColor="@android:color/white" />

</LinearLayout>

ขั้นตอนที่ 3: โค้ดหลัก (MainActivity.kt)

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider

class MainActivity : AppCompatActivity() {
    private lateinit var etTo: EditText
    private lateinit var etSubject: EditText
    private lateinit var etBody: EditText
    private lateinit var tvAttachment: TextView
    private var attachmentUri: Uri? = null

    // 🔑 ใช้ Activity Result API (Modern) แทน onActivityResult
    private val pickFileLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        attachmentUri = uri
        tvAttachment.text = "Attached: ${uri.lastPathSegment ?: "Unknown"}"
        tvAttachment.setTextColor(resources.getColor(android.R.color.holo_blue_dark))
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "Email with Attachment"

        etTo = findViewById(R.id.etTo)
        etSubject = findViewById(R.id.etSubject)
        etBody = findViewById(R.id.etBody)
        tvAttachment = findViewById(R.id.tvAttachment)

        findViewById

📎 ประเภทไฟล์ที่แนบได้ (MIME Type)

// รูปภาพ
intent.type = "image/*"
// PDF
intent.type = "application/pdf"
// ทุกประเภท
intent.type = "*/*"

// หลายไฟล์ (API 18+)
val uris = arrayListOf()
intent.action = Intent.ACTION_SEND_MULTIPLE
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)

⚠️ ข้อควรระวังเรื่อง Permission & Uri

  • ใช้ FLAG_GRANT_READ_URI_PERMISSION เพื่อให้แอปอีเมลอ่านไฟล์ได้
  • หากใช้ FileProvider (สำหรับไฟล์ใน App Private Storage) ต้อง Setup ใน Manifest
  • ACTION_GET_CONTENT คืน Uri ที่เข้าถึงได้ทันที (ไม่ต้อง Permission)
  • Android 10+ (API 29+): ใช้ Scoped Storage, ไม่เข้าถึงไฟล์แอปอื่นโดยตรงได้

📧 Intent Chooser vs Default App

// Chooser: แสดง Dialog ให้เลือกแอปทุกครั้ง (แนะนำ)
startActivity(Intent.createChooser(emailIntent, "Choose email app"))

// Default: เปิดแอป Default ทันที (อาจไม่มี Attachment Support)
startActivity(emailIntent)

ขั้นตอนที่ 4: AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />
<!-- READ_EXTERNAL_STORAGE ไม่ต้องสำหรับ ACTION_GET_CONTENT -->

<application ...>
    <activity android:name=".MainActivity"> ... </activity>

    <!-- สำหรับ FileProvider (หากแชร์ไฟล์ Private) -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

ทดสอบ

  1. รันแอป → กรอก To, Subject, Body
  2. กด "Attach File" → เลือกไฟล์ (รูป, PDF, etc.)
  3. กด "Send Email" → เลือกแอป Gmail/Outlook → ตรวจสอบ Attachment → ส่ง