1. Project introduction
1.1 Background and Meaning
In Android applications, "sharing" is one of the most common cross-app interaction modes. Whether users transfer documents, pictures, audio, video or any type of files through social, email, cloud disk and other third-party applications, they need to rely on system-levelIntentMechanism and content provider (ContentProvider
) to complete seamless docking. Implementing the "Share File" function can not only improve the user experience of the application, but also make the application easier to be disseminated and promoted.
This project is aimed at mainstream versions of Android 5.0 and above, and demonstrates how to:
Create and manage files in internal storage or external private directories;
Use the official recommendedFileProviderSafely expose files to other applications;
Build and send a share intent to share a single or multiple files with any target application;
Processing Android 7.0+Strict document URI restrictions(
FileUriExposedException
);Compatible with Android 10+Scoped Storage(range storage);
UtilizeSimplify development;
Handle runtime permissions and exceptions gracefully.
And on this basis, it provides best practices and extended ideas to help readers integrate the "Share File" function into real projects.
1.2 Project Objectives
File creation and management: Read and write files (text, pictures, PDF, any binary) in the application storage space, and retain sharing paths.
FileProvider Configuration:exist
and
res/xml/file_paths.xml
RegisterFileProvider
and set a shareable directory structure.Share Intent Build:based on
Intent.ACTION_SEND
andIntent.ACTION_SEND_MULTIPLE
, supports single file and multiple file sharing, and sets appropriate MIME type and URI permissions.Runtime permissions: Dynamically apply for necessary storage or media permissions to ensure normal function in Android 6.0+ environment.
Compatibility processing: Handle URI exposure restrictions over Android 7.0, and Scoped Storage (SAF) differences for Android 10+.
Example complete: Concentrated display of all key files and codes, including comment partitions, for easy copying and use;
Extension and optimization: Summarize common pitfalls, performance suggestions, and advanced features that can be considered in the next step (such as cloud sharing, WorkManager background sharing, Compose version, etc.).
2. Explanation of related knowledge
2.1 Overview of Intent Sharing Mechanism
Android sharing mechanism is based onImplicit Intent, core steps:
Construct an Intent containing the operation type, such as
ACTION_SEND
(Single file/single data) orACTION_SEND_MULTIPLE
(Multiple files).Call
()
Specify the MIME type, such as"text/plain"
、"image/jpeg"
、"*/*"
。use
(Intent.EXTRA_STREAM, uri)
orIntent.EXTRA_STREAM
List, attach the file URI to share.Grant read permissions to the target application, usually through
(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.Call
startActivity((intent, "Share to"))
, adjust the system sharing panel.
2.2 FileProvider Principle
Because Android 7.0+ is prohibitedfile://
URI shares files across processes and will throwFileUriExposedException
. Recommended practices:
exist
Statement in the
<provider android:name="" ...>
, and point to an XML resource@xml/file_paths
。exist
file_paths.xml
Define a shareable directory in for example<external-files-path name="shared" path="shared_files/"/>
。use
(context, authority, file)
WillConvert to
content://
URI。authority
Usually it is"${applicationId}.fileprovider"
, it must be consistent with Manifest.
2.3 Scoped Storage and External Storage
Android 9 and below: External storage (
()
) can be read and written freely, but it is requiredWRITE_EXTERNAL_STORAGE
Permissions;Android 10: Introduce Scoped Storage, apply sandboxing, and directly accessing external public directories is restricted; it can be passed
requestLegacyExternalStorage=true
Temporary compatibility;Android 11+: More stringent, recommendedStorage Access Framework(SAF) or access only your own private directory.
For sharing, as long as the file is in the application private directory (
getFilesDir()
orgetExternalFilesDir()
) and exposed through FileProvider to access across applications without additional storage permissions.
2.4 Simplification
Provided by AndroidX, simplify the sharing process:
(activity) .setType(mimeType) .setStream(uri) .setChooserTitle("Share File") .startChooser();
Automatically handle read permission tags and Intent wrappers internally.
Ideas for realization
-
Create a demo file
When the application starts,
getExternalFilesDir("shared")
orgetFilesDir()
Write a test text file in;
-
Configure FileProvider
exist
Register in ;
exist
res/xml/file_paths.xml
Definition in<external-files-path name="shared" path="shared/"/>
;
-
UI layout
exist
activity_main.xml
Place two buttons: "Share a single file" and "Share multiple files"; put another oneTextView
Show sharing results;
-
MainActivity Implementation
Dynamic application CAMERA permission is not required, but it is required
READ_EXTERNAL_STORAGE
orWRITE_EXTERNAL_STORAGE
only on Android ≤9;In the callback of the button click, call
shareSingleFile()
andshareMultipleFiles()
method;
-
shareSingleFile()
Get
File
, tocontent://
URI, by()
;Structure
Intent.ACTION_SEND
,setType()
,putExtra(EXTRA_STREAM, uri)
,addFlags(FLAG_GRANT_READ_URI_PERMISSION)
;Call
startActivity((...))
;
-
shareMultipleFiles()
Structure
ArrayList<Uri>
, add the URIs of multiple files respectively;use
ACTION_SEND_MULTIPLE
,putParcelableArrayListExtra(EXTRA_STREAM, urisList)
;
-
Result processing
After the sharing is completed, if you want to capture and return, you must use it.
startActivityForResult()
, but most third-party applications do not return results.
4. Complete code integration
<!-- ==================== File: ==================== --> <manifest xmlns:andro package=""> <!-- Android 9 If you operate external storage, you need to declare this permission.,But the examples are only in private directories,No storage permission required --> <uses-permission android:name=".WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/> <application android:allowBackup="true" android:label="File Sharing Example" android:theme="@style/"> <activity android:name=".MainActivity"> <intent-filter> <action android:name=""/> <category android:name=""/> </intent-filter> </activity> <!-- FileProvider register --> <provider android:name="" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name=".FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"/> </provider> </application> </manifest>
<!-- ==================== File: res/xml/file_paths.xml ==================== --> <?xml version="1.0" encoding="utf-8"?> <paths xmlns:andro> <!-- Allow sharing app Private external directory:.../Android/data/.../files/shared/ --> <external-files-path name="shared" path="shared/"/> <!-- If you need to share private internal storage,Can be added: <files-path name="internal" path="shared/"/> --> </paths>
<!-- ==================== File: res/layout/activity_main.xml ==================== --> <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:orientation="vertical" android:padding="24dp" android:gravity="center_horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android: android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Share a single file"/> <Button android: android:layout_width="match_parent" android:layout_marginTop="16dp" android:layout_height="wrap_content" android:text="Share multiple files"/> <TextView android: android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="32dp" android:text="Share status: Not operated" android:textSize="16sp"/> </LinearLayout>
// ==================== File: ==================== package ; import ; import ; import ; import ; import .*; import ; import ; import ; import .*; import ; import ; /** * MainActivity: Demonstrate Android file sharing function */ public class MainActivity extends AppCompatActivity { private Button btnShareSingle, btnShareMultiple; private TextView tvStatus; private File sharedDir; @Override protected void onCreate(@Nullable Bundle saved) { (saved); setContentView(.activity_main); // 1. Bind the control btnShareSingle = findViewById(.btn_share_single); btnShareMultiple = findViewById(.btn_share_multiple); tvStatus = findViewById(.tv_status); // 2. Create a sample file directory sharedDir = new File(getExternalFilesDir("shared"), ""); if (!()) (); // 3. Create sample files in the directory createExampleFile("", "This is the sample file 1 Contents。"); createExampleFile("", "This is the sample file 2 Contents。"); createExampleFile("", "This is the sample file 3 Contents。"); // 4. Single file sharing (v -> { File file = new File(sharedDir, ""); if (()) shareSingleFile(file, "text/plain"); else ("The file does not exist: "); }); // 5. Multi-file sharing (v -> { List<File> files = new ArrayList<>(); (new File(sharedDir, "")); (new File(sharedDir, "")); (new File(sharedDir, "")); shareMultipleFiles(files, "text/plain"); }); } /** * Create a sample text file */ private void createExampleFile(String name, String content) { File out = new File(sharedDir, name); try (FileWriter fw = new FileWriter(out)) { (content); } catch (IOException e) { (); ("File creation failed:" + name); } } /** * Share a single file */ private void shareSingleFile(File file, String mimeType) { Uri uri = getUriForFile(file); if (uri == null) return; Intent intent = new Intent(Intent.ACTION_SEND); (mimeType); (Intent.EXTRA_STREAM, uri); (Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity((intent, "Share File")); } /** * Share multiple files */ private void shareMultipleFiles(List<File> files, String mimeType) { ArrayList<Uri> uris = new ArrayList<>(); for (File f : files) { Uri uri = getUriForFile(f); if (uri != null) (uri); } if (()) { ("No file to share"); return; } Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); (mimeType); (Intent.EXTRA_STREAM, uris); (Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity((intent, "Share multiple files")); } /** * Get content:// URI, compatible with each version */ private Uri getUriForFile(File file) { try { // Use FileProvider to generate URI String authority = getPackageName() + ".fileprovider"; return (this, authority, file); } catch (IllegalArgumentException e) { (); ("URI cannot be obtained:" + ()); return null; } } }
5. Code interpretation
-
FileProvider Configuration
exist
Statement in the
<provider>
,authorities="${applicationId}.fileprovider"
Must be with()
Inauthority
Unconsistent;file_paths.xml
Defined<external-files-path name="shared" path="shared/"/>
Share allowedgetExternalFilesDir("shared")
all files under;
-
Sample file creation
createExampleFile()
Write text files to private external storage directories without external storage permissions;The document is written in
Android/data/<pkg>/files/shared/
, automatically clean up after uninstalling the application;
-
Share a single file
Intent.ACTION_SEND
: used for single file sharing;setType("text/plain")
: Tell the system file type;EXTRA_STREAM
: Attachment URI;addFlags(FLAG_GRANT_READ_URI_PERMISSION)
: Grant temporary read permissions to the target application.
-
Share multiple files
ACTION_SEND_MULTIPLE
: Supports multiple files;Similar to single file, but mostly passed
putParcelableArrayListExtra(EXTRA_STREAM, uris)
Add multiple URIs;
-
Runtime compatibility
Android 7.0+ Forced use
content://
URI;FileProvider will issue permissions to each URI internally, and the target application is
onActivityResult
Can be used in ;Android 6.0+ If you need to apply for public external storage operationRead/writePermissions, but the example only uses a private directory and no application is required.
6. Project summary and expansion
6.1 Effect review
Successfully realize sharing with multiple files in single form, overwriting any text, pictures, and binary files.
Adopt the officially recommended FileProvider solution, compatible with Android 7.0+ strict file URI restrictions.
Private directories do not require storage permissions, are safe and reliable, and do not require additional storage applications.
6.2 Common pitfalls and attention
URI permission invalid: Must be for each
Intent
join inFLAG_GRANT_READ_URI_PERMISSION
;Authority inconsistent:
getUriForFile()
ofauthority
Required with Manifestprovider
Consistent, otherwise throw exceptions;Scoped Storage: Android 10+ If you need to access a public directory or SD card, you need to use SAF instead (
Intent.ACTION_OPEN_DOCUMENT
/MediaStore
), FileProvider is only available for private directories;Big file sharing: When sharing large files, do not read, write or copy files in the UI thread;
6.3 Extensible direction
-
Customize
use
Simplify Intent construction and permission processing;
-
Cloud sharing
Upload the file to the cloud before sharing, generate a publicly accessible URL, and then pass
ACTION_SEND
Share link;
-
Timely sharing in the background
Combined
WorkManager
Generate reports regularly and share them automatically;
-
Jetpack Compose implementation
use
Intent
andrememberLauncherForActivityResult
Integrated share button;
-
Native CameraX and MediaStore
Before sharing pictures or videos, take photos/record and save them to MediaStore via CameraX before sharing;
-
Advanced MIME Negotiation
Adjust MIME for different target applications, such as sharing Office documents (
application/msword
) or compressed package (application/zip
);
-
Share progress feedback
For large files or network sharing, you can display the status of "Preparing", "Shared", and "Failed" in the UI;
-
Secure encryption sharing
Use AES encryption before sharing files and decrypt them on the receiver or in the target application.
The above is the detailed content of the file sharing function based on Android. For more information about Android file sharing, please follow my other related articles!