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 FileProvider: chia sẻ file cache bằng content URI

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

Bạn có một file trong cache riêng của app và muốn gửi sang ứng dụng khác. Gửi đường dẫn tuyệt đối không làm app nhận có quyền đọc. Giải pháp trong bài là FileProvider, một content URI và quyền đọc tạm thời cho đúng file được gửi.

Đối chiếu tài liệu AndroidX Core ngày 31/10/2026. Mẫu giả định project Android Kotlin dùng AppCompatActivity, AndroidX Core và minSdk từ 23. Đây là hướng dẫn tích hợp vào project có sẵn, chưa chạy Android build hoặc thử Sharesheet trên thiết bị.

1. Khai báo một provider riêng

Tạo lớp ShareFileProvider.kt trong package của ứng dụng. Ví dụ dùng package giả com.example.share; thay bằng namespace thật ở cả mã và manifest. Kế thừa FileProvider giúp làm rõ component được khai báo, thay vì dựa vào sử dụng trực tiếp lớp thư viện trên mọi thiết bị.

package com.example.share

import androidx.core.content.FileProvider

class ShareFileProvider : FileProvider()

Trong phần application của manifest có sẵn, thêm provider sau. ${applicationId} là placeholder được Android Gradle xử lý, giúp authority theo đúng variant. Nó không phải biến để bạn thay bằng đường dẫn file.

<provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:name="com.example.share.ShareFileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/share_paths" />
</provider>

Tạo res/xml/share_paths.xml. Chỉ thư mục share/ dưới cache được cấu hình để tạo URI; không mở toàn bộ cache bằng path="." để xử lý một lỗi đường dẫn cụ thể.

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <cache-path name="shared_reports" path="share/" />
</paths>

Tên shared_reports là đoạn tên dùng trong URI, còn share/ là thư mục thực. Cấu hình thư mục cho phép provider tạo URI cho các file bên trong; quyền gửi cho app nhận vẫn phải được cấp cho URI cụ thể.

2. Tạo file mẫu và gửi quyền đọc

Extension sau gọi từ một Activity đang mở, ví dụ trong listener của nút chia sẻ đã có. Nó chỉ ghi một file text nhỏ với dữ liệu minh họa công khai. Với báo cáo lớn, chuyển việc tạo file sang tác vụ nền và xử lý lỗi theo luồng UI của dự án.

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.ClipData
import android.content.Intent
import android.widget.Toast
import androidx.core.content.FileProvider
import java.io.File
import java.io.IOException

fun Activity.shareDemoReport() {
    try {
        val folder = File(cacheDir, "share")
        if (!folder.isDirectory && !folder.mkdirs()) {
            throw IOException("Không tạo được thư mục chia sẻ")
        }
        val report = File.createTempFile("demo-", ".txt", folder)
        report.writeText("Báo cáo mẫu AeDev\n", Charsets.UTF_8)
        val uri = FileProvider.getUriForFile(
            this, "$packageName.fileprovider", report
        )
        val intent = Intent(Intent.ACTION_SEND).apply {
            type = "text/plain"
            putExtra(Intent.EXTRA_STREAM, uri)
            clipData = ClipData.newRawUri("Báo cáo mẫu", uri)
            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        }
        startActivity(Intent.createChooser(intent, "Chia sẻ báo cáo"))
    } catch (error: ActivityNotFoundException) {
        Toast.makeText(this, "Không có ứng dụng nhận phù hợp", Toast.LENGTH_SHORT).show()
    } catch (error: IOException) {
        Toast.makeText(this, "Không tạo được báo cáo", Toast.LENGTH_SHORT).show()
    }
}

Gọi shareDemoReport() từ Activity chỉ khi người dùng chọn chia sẻ. EXTRA_STREAM mang URI của file, MIME mô tả dữ liệu, còn flag cấp quyền đọc tạm thời. Không thêm quyền ghi vì app nhận chỉ cần đọc báo cáo.

3. Kiểm tra authority, đường dẫn và thời điểm xóa

Trước tiên xác nhận authority trong merged manifest bằng authority truyền vào getUriForFile. Với applicationIdSuffix cho debug, so sánh giá trị sau merge thay vì chỉ nhìn package ở đầu file Kotlin.

Chọn một ứng dụng có thể nhận file text rồi thử mở nội dung. Mở được chooser chỉ chứng minh giao diện chọn app đã xuất hiện; chưa chứng minh app nhận đã đọc được file. Thử cả variant debug và release nếu có authority khác nhau.

Không xóa file ngay sau startActivity: app nhận có thể chưa đọc xong. Demo tạo tên file riêng cho mỗi lần chia sẻ để tránh ghi đè nội dung đang được đọc. Sản phẩm cần chính sách dọn các file cache cũ phù hợp; ví dụ chưa triển khai lịch dọn đó và cache cũng không phải nơi lưu báo cáo bền vững.

Lỗi thường gặp và giới hạn

Lỗi không tìm thấy configured root thường do file nằm ngoài cache/share hoặc resource paths không được provider dùng đúng. Kiểm tra cấu hình trước khi mở rộng root. Lỗi authority thường liên quan applicationId, variant hoặc tên provider trong manifest.

Không bắt mọi Exception rồi coi đó là chia sẻ thành công. Mẫu xử lý lỗi tạo file và không có Activity phù hợp, còn lỗi cấu hình cần được phát hiện trong quá trình tích hợp. Không gửi file có token hoặc dữ liệu riêng tư chỉ vì nó đang nằm trong cache.

XML trong bài đã được parse và rà phạm vi khai báo; Kotlin được rà theo API chính thức, chưa có kết quả chạy trên Android. Bước xác nhận cuối vẫn là app nhận đọc được đúng file với quyền tối thiểu, sau khi bạn kiểm tra trên thiết bị mục tiêu.

Nguồn tham khảo

  • Android: thiết lập chia sẻ file
  • AndroidX Core: FileProvider, paths và quyền URI
  • Android: gửi nội dung file qua Sharesheet

Tags: AndroidFileProviderKotlin
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 Intent extra: thiếu dữ liệu khác với giá trị 0

by Suong Nguyen
01/11/2026
0

Kết hợp hasExtra, getIntExtra và kiểm tra phạm vi để phân biệt không truyền dữ liệu, giá trị hợp lệ bằng 0 và dữ liệu sai.

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

Android ACTION_VIEW: mở liên kết HTTPS và xử lý khi không có app nhận

by Suong Nguyen
30/10/2026
0

Mở một URL cố định từ Activity, xử lý ActivityNotFoundException và tránh coi resolveActivity là điều kiện bắt buộc để launch.

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

Android NumberFormat: tách locale, mã tiền tệ và giá trị cần hiển thị

by Suong Nguyen
29/10/2026
0

Định dạng giá trị VND và USD bằng locale rõ ràng, giữ số liệu gốc và phát hiện phần lẻ không phù hợp trước khi hiển thị.

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

Android ClipboardManager: sao chép text và tránh thông báo trùng từ Android 13

by Suong Nguyen
28/10/2026
0

Tạo ClipData đúng label và nội dung, ghi vào clipboard sau thao tác bấm và điều chỉnh phản hồi sao chép theo phiên bản Android.

Next Post
Lập trình viên chuẩn bị phỏng vấn fresher React Native với laptop, điện thoại và thẻ câu hỏi

Vì sao Array(3).map không gọi callback ba lầ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 useColorScheme: đổi theme mà không cache màu từ module
  • Return trong finally có thể che cả return lẫn lỗi ban đầu
  • Android Intent extra: thiếu dữ liệu khác với giá trị 0

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