小红书分享踩坑和解决

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

下载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         }

 

发表评论

评论已关闭。

相关文章