您的当前位置:首页正文

小红书分享踩坑和解决

2024-10-17 来源:个人技术集锦
小红书官方介入链接:

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

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

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

例如我的代码如下:

AndroidManifest文件<provider            android:name="androidx.core.content.FileProvider"            android:authorities="${applicationId}.FileProvider"            android:exported="false"            android:grantUriPermissions="true"            >            <meta-data                android:name="android.support.FILE_PROVIDER_PATHS"                android:resource="@xml/provider_paths"                />        </provider>
res目录下的xml配置文件<?xml version="1.0" encoding="utf-8"?><paths>    <cache-path        name="cache"        path="."        /> <!--Context.getCacheDir() -->    <files-path        name="files"        path="."        /> <!--Context.getFilesDir() -->    <external-path        name="external"        path="."        />  <!--  Environment.getExternalStorageDirectory()-->    <external-cache-path        name="external-cache"        path="."        /> <!--  Context.getExternalCacheDir() -->    <external-files-path        name="external-files"        path="."        /> <!--  Context.getExternalFilesDir() -->    <external-files-path        name="opensdk_external"        path="Images"        />    <root-path        name="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 = title                    this.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                )            }            return contentUri        }        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() ?: 0                val timePositionUs = (duration / 100f * percent).toLong() * 1000                bitmap = retriever.getFrameAtTime(                    timePositionUs, MediaMetadataRetriever.OPTION_CLOSEST                )            } catch (e: Exception) {                log(type = LogType.E, errorThrowable = e)                e.printStackTrace()            } finally {                retriever.release()            }            return bitmap        }

Top