最近的项目中需要用到分享功能,之前做分享一般都是直接用三方聚合类的SDK,比如国内的友盟、ShareSdk。
老大提到说可以试试看直接调用系统的分享,这个我之前还真没尝试过,所以通过本篇文章记录一下如何使用系统分享(Android Sharesheet)。
Android Sharesheet简介
Android Sharesheet 通过Intent与其内含的Extra让用户可以使用他们喜爱的应用快速轻松地分享信息。
常用的MIME类型
使用Android Sharesheet进行分享时,可以指定分享内容的类型,如果目标App有注册、处理指定的类型,则会在Android Sharesheet的面板中显示,下面是一些常用的类型:
object MimeType {
const val TEXT_PLAIN = "text/plain"
const val TEXT_RTF = "text/rtf"
const val TEXT_HTML = "text/html"
const val TEXT_JSON = "text/json"
const val IMAGE_JPEG = "image/jpeg"
const val IMAGE_PNG = "image/png"
const val IMAGE_GIT = "image/gif"
const val IMAGE_ALL = "image/*"
const val VIDEO_MP4 = "video/mp4"
const val VIDEO_3GP = "video/3gp"
}
更多的类型可以参考媒体类型的 IANA 官方注册表
分享文本
可以通过如下代码分享纯文本或者网页:
class SystemShareActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<LayoutSystemShareActivityBinding>(this, R.layout.layout_system_share_activity)
binding.btnShareText.setOnClickListener {
val onlyTextShareIntent = Intent().apply {
//actoin 必须使用Intent.ACTION_SEND
action = Intent.ACTION_SEND
//设置文本内容
putExtra(Intent.EXTRA_TEXT, "this is test share text")
//指定类型
type = MimeType.TEXT_PLAIN
}
val shareIntent = Intent.createChooser(onlyTextShareIntent, "ShareTextTitle")
startActivity(shareIntent)
}
binding.btnShareUrl.setOnClickListener {
val urlShareIntent = Intent().apply {
action = Intent.ACTION_SEND
//设置网页链接
putExtra(Intent.EXTRA_TEXT, "https://juejin.cn/")
//设置标题
putExtra(Intent.EXTRA_TITLE, "ShareUrlTitle")
//指定类型
type = MimeType.TEXT_HTML
}
val shareIntent = Intent.createChooser(urlShareIntent, null)
startActivity(shareIntent)
}
}
}
分享文本效果如图:
分享网页效果如图:
分享文件
文件分享需要使用Uri,所以需要配置FileProvider。
//在res文件夹下新建xml资源文件夹,并新建file_path.xml资源文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="images"
path="." />
<cache-path
name="cache-path"
path="." />
<external-path
name="external_storage_root"
path="." />
<external-cache-path
name="external_cache_path"
path="." />
</paths>
//在Manifest中配置FileProvider
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
</application>
</manifest>
分享图片或者视频
可以通过如下代码分享图片或者视频:
class SystemShareActivity : AppCompatActivity() {
private val pickPhoto = registerForActivityResult(PickSinglePhotoContract()) { uri ->
if (uri != null) {
val pictureShareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
//设置图片Uri
putExtra(Intent.EXTRA_STREAM, uri)
//指定类型
type = MimeType.IMAGE_JPEG
}
val shareIntent = Intent.createChooser(pictureShareIntent, "SharePictureTitle")
startActivity(shareIntent)
}
}
private val pickVideo = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
if (uri != null) {
val pictureShareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
//设置视频Uri
putExtra(Intent.EXTRA_STREAM, uri)
//指定类型
type = MimeType.VIDEO_MP4
}
val shareIntent = Intent.createChooser(pictureShareIntent, "ShareVideoTitle")
startActivity(shareIntent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<LayoutSystemShareActivityBinding>(this, R.layout.layout_system_share_activity)
binding.btnSharePicture.setOnClickListener {
pickPhoto.launch(null)
}
binding.btnShareVideo.setOnClickListener {
pickVideo.launch(MimeType.VIDEO_All)
}
}
}
分享图片效果如图:
分享视频效果如图:
多文件分享(混合类型)
可以分享多张图片,多个视频,或者图片+视频。
代码如下:
class SystemShareActivity : AppCompatActivity() {
private val sharePhotoUri = ArrayList<Uri>()
private val shareVideoUrl = ArrayList<Uri>()
private val pickPhotos = registerForActivityResult(PickMultipleMediumContract()) { uriList ->
if (uriList.isNotEmpty()) {
sharePhotoUri.addAll(uriList)
val photoShareIntent = Intent().apply {
action = Intent.ACTION_SEND_MULTIPLE
putParcelableArrayListExtra(Intent.EXTRA_STREAM, sharePhotoUri)
type = MimeType.IMAGE_ALL
}
startActivity(Intent.createChooser(photoShareIntent, "SharePhotosTitle"))
}
}
private val pickVideos = registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { uri ->
if (uri.isNotEmpty()) {
shareVideoUrl.addAll(uri)
val videoShareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND_MULTIPLE
putParcelableArrayListExtra(Intent.EXTRA_STREAM, shareVideoUrl)
type = MimeType.VIDEO_All
}
val shareIntent = Intent.createChooser(videoShareIntent, "ShareVideosTitle")
startActivity(shareIntent)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<LayoutSystemShareActivityBinding>(this, R.layout.layout_system_share_activity)
binding.btnSharePictures.setOnClickListener {
pickPhotos.launch(null)
}
binding.btnShareVideos.setOnClickListener {
pickVideos.launch(MimeType.VIDEO_All)
}
binding.btnShareMultipleMedium.setOnClickListener {
val mediumUris = ArrayList<Uri>()
mediumUris.addAll(sharePhotoUri)
mediumUris.addAll(shareVideoUrl)
if (mediumUris.isNotEmpty()) {
val mediumShareIntent = Intent().apply {
action = Intent.ACTION_SEND_MULTIPLE
putParcelableArrayListExtra(Intent.EXTRA_STREAM, mediumUris)
type = MimeType.ALL
}
startActivity(Intent.createChooser(mediumShareIntent, "ShareMultipleMediumTitle"))
}
}
}
}
多图分享效果如图:
多视频分享效果如图:
图片视频混合分效果如图: