ภาพรวม
การแชร์ข้อมูล (Sharing) ใน Android ใช้ **Implicit Intent** ด้วย Action Intent.ACTION_SEND ร่วมกับ Intent.createChooser() เพื่อแสดง Dialog ให้ผู้ใช้เลือกแอปปลายทาง (Email, Messenger, Social, Bluetooth, ฯลฯ)
ขั้นตอนการสร้าง
1. Layout (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:padding="24dp">
<TextView
android:id="@+id/tvContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="https://www.example.com/article/awesome-tips"
android:textSize="18sp"
android:autoLink="web"
android:layout_marginBottom="24dp" />
<Button
android:id="@+id/btnShareText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="แชร์ข้อความนี้" />
<Button
android:id="@+id/btnShareImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="แชร์รูปภาพ (ตัวอย่าง)" />
</LinearLayout>
2. MainActivity.java
package com.example.myapplication;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
private TextView tvContent;
private Button btnShareText, btnShareImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvContent = findViewById(R.id.tvContent);
btnShareText = findViewById(R.id.btnShareText);
btnShareImage = findViewById(R.id.btnShareImage);
// แชร์ข้อความธรรมดา (Text/URL)
btnShareText.setOnClickListener(v -> shareText());
// แชร์รูปภาพ (ต้องมีไฟล์จริง)
btnShareImage.setOnClickListener(v -> shareImage());
}
private void shareText() {
String text = tvContent.getText().toString().trim();
if (text.isEmpty()) {
Toast.makeText(this, "ไม่มีข้อความให้แชร์", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.putExtra(Intent.EXTRA_SUBJECT, "แชร์จากแอปของฉัน"); // Optional: สำหรับ Email
// สร้าง Chooser Dialog
Intent chooser = Intent.createChooser(intent, "แชร์ผ่าน...");
// Verify มีแอปรับโจทย์หรือไม่
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
} else {
Toast.makeText(this, "ไม่มีแอปที่รองรับการแชร์ข้อความ", Toast.LENGTH_SHORT).show();
}
}
private void shareImage() {
// ตัวอย่าง: คัดลอกรูปจาก Assets → Cache → แชร์
// ใน Production ใช้ไฟล์จริงจาก Storage/ContentProvider
try {
File cacheFile = new File(getCacheDir(), "shared_image.png");
copyFromAssetsToCache("sample_image.png", cacheFile);
// ใช้ FileProvider เพื่อความปลอดภัย (API 24+ ต้องใช้)
Uri contentUri = FileProvider.getUriForFile(
this,
getPackageName() + ".fileprovider",
cacheFile
);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // สำคัญ!
Intent chooser = Intent.createChooser(intent, "แชร์รูปภาพผ่าน...");
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
} else {
Toast.makeText(this, "ไม่มีแอปที่รองรับการแชร์รูปภาพ", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
Toast.makeText(this, "เตรียมรูปภาพล้มเหลว: " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void copyFromAssetsToCache(String assetName, File dest) throws IOException {
try (InputStream is = getAssets().open(assetName);
FileOutputStream fos = new FileOutputStream(dest)) {
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
}
}
}
3. AndroidManifest.xml (สำหรับ FileProvider)
<manifest ...>
<application ...>
<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>
</manifest>
4. res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="https://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="." />
</paths>
MIME Types ที่ใช้บ่อย
| ประเภท | MIME Type | Extra Key |
|---|---|---|
| ข้อความ/URL | text/plain | EXTRA_TEXT |
| HTML | text/html | EXTRA_TEXT, EXTRA_HTML_TEXT |
| อีเมล (RFC822) | message/rfc822 | EXTRA_EMAIL, EXTRA_SUBJECT, EXTRA_TEXT |
| รูปภาพ | image/* (jpeg, png, gif) | EXTRA_STREAM (Uri) |
| วิดีโอ | video/* | EXTRA_STREAM |
| ไฟล์ทั่วไป | application/* | EXTRA_STREAM |
| หลายไฟล์ | Action: ACTION_SEND_MULTIPLE | EXTRA_STREAM (ArrayList<Uri>) |
แชร์ไฟล์หลายไฟล์ (Multiple Files)
ArrayListuris = new ArrayList<>(); uris.add(contentUri1); uris.add(contentUri2); Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); intent.setType("image/*"); intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(Intent.createChooser(intent, "แชร์หลายรูป"));
Direct Share Targets (Android 10+ / API 29+)
เพื่อให้แอปปรากฏใน **Direct Share** (แถบแชร์โดยตรงบน Sharesheet) ให้เพิ่ม `ShortcutManager` และ `ShareTarget` ใน Manifest (XML) - รายละเอียดดูในเอกสาร Android Developers: Receiving simple data from other apps
Best Practices
- ใช้
Intent.createChooser()ทุกครั้ง (User control, ไม่บังคับแอปเดียว) - เช็ค
resolveActivity()ก่อน startActivity ป้องกัน Crash - ใช้ **FileProvider** สำหรับไฟล์ (API 24+ ห้ามใช้ file:// URI)
- เพิ่ม
FLAG_GRANT_READ_URI_PERMISSIONให้ Uri - ตั้งค่า MIME Type ให้เฉพาะเจาะจง (image/png แทน image/*) เพื่อกรองแอปที่เกี่ยวข้อง
- สำหรับข้อความยาว ใช้ EXTRA_HTML_TEXT ร่วมกับ EXTRA_TEXT
สรุป
แชร์ข้อมูลใน Android = Intent.ACTION_SEND + MIME Type + Extra Data + Intent.createChooser() + FileProvider (สำหรับไฟล์) รองรับ Text, HTML, Email, Image, Video, Multiple files ได้ครบครัน