aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
SAVED POSTS
aedev.net
  • Trang chủ
  • AI
  • Mobile
  • Flutter
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
No Result
View All Result
aedev.net
No Result
View All Result
Minh họa môi trường phát triển React Native với laptop, Android emulator và iOS simulator

Android Sharesheet: chia sẻ văn bản và đường dẫn bằng ACTION_SEND

Suong Nguyen by Suong Nguyen
27/10/2026
in Lập trình Mobile
0
585
SHARES
3.2k
VIEWS
Summarize with ChatGPTShare to Facebook

Ứng dụng có nút “Chia sẻ bài viết” không cần tự duy trì danh sách mọi ứng dụng nhận nội dung. Android cung cấp Sharesheet để người dùng chọn nơi gửi. Phần việc của bạn là chuẩn bị đúng dữ liệu và mở giao diện hệ thống từ thao tác của người dùng.

Bài dành cho dự án Android dùng Kotlin và đã có Activity. Ví dụ chỉ chia sẻ văn bản có đường dẫn công khai, không gửi file hay ảnh. Các API Intent được đối chiếu tài liệu Android ngày 27/10/2026; lượt biên tập chưa build APK hoặc kiểm tra trên thiết bị.

1. Chọn action, MIME type và extra đúng vai trò

ACTION_SEND diễn đạt ý định gửi nội dung sang ứng dụng khác. Với văn bản, dùng MIME type text/plain và đặt nội dung trong Intent.EXTRA_TEXT. Một URL trong phần text vẫn là nội dung để chia sẻ, khác với ACTION_VIEW dùng để mở một địa chỉ.

Intent.createChooser() bọc intent gửi và yêu cầu giao diện chọn nơi chia sẻ. Không gán package cụ thể nếu yêu cầu sản phẩm là cho người dùng tự chọn. Cũng không dùng */* cho trường hợp đã biết rõ nội dung là text, vì kiểu cụ thể giúp hệ thống tìm ứng dụng phù hợp hơn.

2. Tách một hàm gọi từ Activity

Thêm file Kotlin dưới đây vào package của ứng dụng; khai báo package cần khớp dự án. Hàm extension nhận một Activity còn hoạt động, chẳng hạn this trong callback bấm nút của màn hình.

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri

fun Activity.shareArticle(title: String, publicUrl: String): Boolean {
    require(title.isNotBlank()) { "Title must not be blank" }
    val uri = Uri.parse(publicUrl)
    require(uri.scheme == "https" && !uri.host.isNullOrBlank()) {
        "Expected a public HTTPS URL"
    }

    val send = Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
        putExtra(Intent.EXTRA_TEXT, "${title.trim()}\n$publicUrl")
    }
    return try {
        startActivity(Intent.createChooser(send, null))
        true
    } catch (error: ActivityNotFoundException) {
        false
    }
}

Điều kiện HTTPS ở đây là chính sách của ví dụ cho link bài viết. Nó không phải bộ xác minh URL hoàn chỉnh: chưa kiểm tra link có tồn tại, có công khai thật hoặc chứa thông tin nhạy cảm hay không. Hãy tạo link chia sẻ từ dữ liệu đã kiểm soát, thay vì truyền nguyên địa chỉ có token từ màn hình đăng nhập.

Hàm trả false khi không khởi động được Activity phù hợp theo ngoại lệ được bắt. Các require dành cho đầu vào sai của code gọi và vẫn ném lỗi; không dùng chúng như thông báo validation trực tiếp cho người dùng.

3. Gọi sau khi người dùng bấm chia sẻ

Ví dụ đặt đoạn này trong callback của nút thuộc Activity. Cần import android.widget.Toast nếu dùng Toast:

val opened = shareArticle("AeDev", "https://aedev.net/")
if (!opened) {
    Toast.makeText(this, R.string.share_unavailable, Toast.LENGTH_SHORT).show()
}

Khai báo chuỗi mặc định trong res/values/strings.xml của ứng dụng:

<resources>
    <string name="share_unavailable">Không mở được bảng chia sẻ.</string>
</resources>

Nếu file đã có phần tử resources, chỉ thêm phần tử string vào đó. Không tạo hai gốc XML. Dữ liệu mẫu chỉ là tên blog và URL công khai; thay bằng tiêu đề cùng link của bài đang hiển thị trong sản phẩm.

Không gọi hàm tự động mỗi lần màn hình render hoặc Activity được tạo lại. Chia sẻ là một hành động ra ngoài ứng dụng, nên gắn nó với thao tác bấm rõ ràng. Nếu gọi từ một lớp khác, truyền Activity ở ranh giới UI thay vì giữ Activity lâu dài trong singleton.

4. Kiểm tra cả phía nhận

Trên thiết bị thử nghiệm, bấm nút và chọn một ứng dụng có thể nhận text. Xác nhận tiêu đề, dấu tiếng Việt, dòng mới và URL còn đúng. Sau đó hủy Sharesheet rồi trở về ứng dụng; màn hình cần tiếp tục hoạt động bình thường.

Thử nhiều ứng dụng nhận khi có thể. Một ứng dụng có thể biến URL thành preview, bỏ qua một số metadata hoặc trình bày dòng mới khác ứng dụng khác. Đừng viết kiểm tra đòi mọi nơi nhận phải có giao diện giống hệt nhau.

Nếu muốn chia sẻ ảnh hoặc file, cần quy trình URI và quyền đọc phù hợp. Không thay EXTRA_TEXT thành đường dẫn file local rồi cho rằng ứng dụng khác đọc được. Đó là một bài toán khác với text trong bài này.

Giới hạn và lỗi thường gặp

Giá trị true chỉ cho biết lời gọi mở chooser không ném ngoại lệ được xử lý. Nó không xác nhận người dùng đã chọn đích, gửi tin thành công hay người nhận đã đọc. Không dùng biến opened để cộng ngay một lượt “chia sẻ thành công” mang ý nghĩa gửi hoàn tất.

Nếu không thấy ứng dụng mong muốn, kiểm tra action, MIME type và khả năng nhận của ứng dụng đó trước khi thêm package cố định. Nếu không biên dịch được R.string.share_unavailable, kiểm tra resource đã được thêm đúng module và tên package của file Kotlin.

Hãy giữ ví dụ text nhỏ, rõ ràng và dễ kiểm tra trước. Sau khi xác nhận trên thiết bị, bạn có thể bổ sung preview hoặc đo sự kiện phù hợp với yêu cầu sản phẩm, thay vì suy luận từ việc bảng chia sẻ đã mở.

Nguồn tham khảo

  • Android: Gửi dữ liệu sang ứng dụng khác bằng Sharesheet
  • Android API: Intent, ACTION_SEND và EXTRA_TEXT
  • Android: Common intents và ACTION_VIEW

Tags: AndroidKotlinSharesheet
SummarizeShare234
Suong Nguyen

Suong Nguyen

Related Stories

Minh họa môi trường phát triển React Native với laptop, Android emulator và iOS simulator

Android plurals: vì sao getQuantityString cần truyền count hai lần?

by Suong Nguyen
26/10/2026
0

Tổ chức resource tiếng Việt và mặc định, phân biệt số lượng chọn plural với tham số định dạng và xử lý empty state có chủ đích.

Minh họa môi trường phát triển React Native với laptop, Android emulator và iOS simulator

Android WorkManager định kỳ: chu kỳ sáu giờ không phải giờ chạy chính xác

by Suong Nguyen
25/10/2026
0

Dùng PeriodicWorkRequest và unique work để hiểu lịch nền có ràng buộc, tránh kỳ vọng chạy chính xác theo đồng hồ hoặc tạo trùng lịch.

Minh họa môi trường phát triển React Native với laptop, Android emulator và iOS simulator

Android SavedStateHandle: giữ bộ lọc khi process bị hệ thống tạo lại

by Suong Nguyen
24/10/2026
0

Phân biệt ViewModel, SavedStateHandle và lưu trữ bền vững để phục hồi đúng trạng thái tìm kiếm trên Android.

Minh họa môi trường phát triển React Native với laptop, Android emulator và iOS simulator

Android Photo Picker: chọn ảnh bằng URI và quản lý quyền đọc đúng vòng đời

by Suong Nguyen
23/10/2026
0

Tạo luồng chọn một ảnh bằng Activity Result, xử lý hủy chọn và giữ quyền URI khi cần upload nền.

0 0 votes
Article Rating
Subscribe
Login
Notify of
guest
guest
0 Comments
Oldest
Newest Most Voted
AE Dev

AE Dev mang đến các bài viết về lập trình, mobile app, backend, frontend, WordPress và công nghệ, phù hợp cho developer muốn học hỏi và cập nhật kiến thức thực tế.

Recent Posts

  • React Native SectionList: nhóm dữ liệu với key và tiêu đề riêng cho từng phần
  • Phỏng vấn JavaScript: Object.is khác === thế nào với NaN, +0 và -0?
  • Android Sharesheet: chia sẻ văn bản và đường dẫn bằng ACTION_SEND

Categories

  • AI
  • Backend
  • Đánh giá
  • DevOps
  • Flutter
  • Hướng dẫn
  • Lập trình Mobile
  • Phỏng vấn
  • React Native
  • Uncategorized

Weekly Newsletter

  • Buy JNews
  • Support Forum
  • Pre-sale Question
  • Contact Us

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

Welcome Back!

Login to your account below

Forgotten Password?

Retrieve your password

Please enter your username or email address to reset your password.

Log In
No Result
View All Result
  • Trang chủ
  • AI
  • Mobile
  • React Native
  • Backend
  • DevOps
  • Hướng dẫn
  • Flutter

© 2026 AE Dev - Blog công nghệ, lập trình và chia sẻ kiến thức IT.

wpDiscuz
0
0
Would love your thoughts, please comment.x
()
x
| Reply