小红书官方介入链接:
小红书分享开放平台

下载sdk文件,位置如下图所示

之后可以按照官方文档进行开发,接入也较简单,这里主要是说明一些隐藏的坑点

一、分享应用内的文件到小红书(这里主要是指应用包名下的文件内容),需要注意setFileProviderAuthority()这个方法。

例如我的代码如下:

AndroidManifest文件<providerandroid:name="androidx.core.content.FileProvider"android:authorities="${applicationId}.FileProvider"android:exported="false"android:grantUriPermissions="true"
            >
            <meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/provider_paths"
                />
        </provider>
res目录下的xml配置文件<?xml version="1.0" encoding="utf-8"?>
<paths>
    <cache-pathname="cache"path="."
        /> <!--Context.getCacheDir()-->
    <files-pathname="files"path="."
        /> <!--Context.getFilesDir()-->

    <external-pathname="external"path="."
        />  <!--Environment.getExternalStorageDirectory()-->
    <external-cache-pathname="external-cache"path="."
        /> <!--Context.getExternalCacheDir()-->
    <external-files-pathname="external-files"path="."
        /> <!--Context.getExternalFilesDir()-->
    <external-files-pathname="opensdk_external"path="Images"
        />
    <root-pathname="opensdk_root"path=""
        />
</paths>

像我的项目配置的话,
需要设置的代码如下

XhsShareSdk.registerApp(context, XHS_APP_KEY,
XhsShareGlobalConfig().setEnableLog(
true).setClearCacheWhenShareComplete(true)//重点是下面的这句话,设置为自己应用的 Authority .setFileProviderAuthority("${context.packageName}.FileProvider")
,
object : XhsShareRegisterCallback {
override fun onSuccess() {
log {
"xhs---onSuccess: 注册成功!"}
}

override fun onError(
errorCode: Int,
errorMessage: String,
@Nullable exception: Exception
?) {
log {
"xhs---onError: 注册失败!errorCode: $errorCode errorMessage: $errorMessage exception: $exception"}
}
})

二、
小红书构造方法的坑:

XhsNote().apply {
title
= getTitleString() //正文,String content = getContentString() //标题,String imageInfo =XhsImageInfo(listOf(
XhsImageResourceBean.fromUrl(
"网络图片 url"),
XhsImageResourceBean.fromUrl(
"网络图片 url")))
}

小红书的示例代码和说明,都说的很简单,可以直接使用fromUrl这个方法进行构造,他会自动识别是网络图片还是本地图片。不需要手动处理了。

但是,之后,你就会发现,分享网络资源没有问题,但是如果分享的内容是自己应用内部的文件,就无论如何,都分享不成功,到了小红书APP,就提示未获取到图片或者视频。

请看SDK代码

小红书SDK里面判断了是否是网络地址,然后通过File的构造方法,调用了顶部的Uri.fromFile(filePath),这个方法是存在问题的。

安卓7.0强制启用了striceMode策略,无法直接暴露file://类型的URI了。如果使用的公共目录分享文件,还是可以成功的,但是如果分享的是应用内部的文件,就会出现没有访问权限的问题。所以小红书APP,就会一直报为获取资源的问题。

解决办法:

使用
XhsImageResourceBean(Uri)方式去构造视频和图片的对象。示例代码如下:

fun shareXHS(
activity: Activity
=requireNotNull(SnsHelper.mainActivity),
filePath: String
//传递过来文件地址 ) {
val xhsPackageNames
= arrayOf("com.xingin.xhs")//获取赋予权限的URI val uri =getContentUriForFileProvider(
filePath
=filePath,
packages
=xhsPackageNames
)
log {
"xhs--- FilePath=$filePath \n,uri:$uri, "}
val title
="标题内容"val content="内容文字" try{//获取视频的首帧作为封面图 val bitmap=getThumbnailFromVideo(filePath)
val tempFile
= File("${activity.cacheDir.absolutePath}/cameraShooting", "tempFileForShare.png")
val stream
=FileOutputStream(tempFile)
bitmap
?.compress(Bitmap.CompressFormat.PNG, 100, stream)
stream.close()
//获取首帧的图片URI val picUri =getContentUriForFileProvider(
filePath
=tempFile.absolutePath,
packages
=xhsPackageNames
)
val xhsNote
=XhsNote().apply {this.title =titlethis.content =content
videoInfo
=XhsVideoInfo(//通过URI的方式,构建数据 XhsVideoResourceBean(uri),
XhsImageResourceBean(picUri)
)
//封面 }//分享数据 val sessionId =XhsShareSdk.shareNote(activity, xhsNote)
}
catch(e:Exception){ }
}
fun getContentUriForFileProvider(
filePath: String,
packages: Array
<String> =emptyArray(),
context: Context
=CoreApp.getContext(),
): Uri {
//根据文件路径,生成关联的 content://内容 URI val file =File(filePath)
val contentUri
=FileProvider.getUriForFile(
context,
"${context.packageName}.FileProvider",
file
)
//赋予权限 packages.forEach {
context.grantUriPermission(
it,
contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
)
}
returncontentUri
}
fun getThumbnailFromVideo(path: String, percent: Int
= 0): Bitmap?{
val retriever
=MediaMetadataRetriever()
var bitmap: Bitmap
? = null try{
retriever.setDataSource(path)
val duration
=retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLongOrNull() ?: 0val timePositionUs= (duration / 100f * percent).toLong() * 1000bitmap=retriever.getFrameAtTime(
timePositionUs, MediaMetadataRetriever.OPTION_CLOSEST
)
}
catch(e: Exception) {
log(type
= LogType.E, errorThrowable =e)
e.printStackTrace()
}
finally{
retriever.release()
}
returnbitmap
}

标签: none

添加新评论