小紅書分享踩坑和解決

来源:https://www.cnblogs.com/zxxiaoxia/p/18373731
-Advertisement-
Play Games

存儲區​ Android 一開始就將存儲區分為內部存儲和外部存儲,對應手機自帶的存儲和可插拔的 sd 卡(可類比於 PC 的硬碟和 U盤)。 內部存儲容量有限,Google 建議 App 數據儘量存儲於外部存儲中。 隨著硬體技術發展,自帶大容量空間的手機開始出現,關於內部存儲的描述逐漸偏離現實了,於 ...


小紅書官方介入鏈接:小紅書分享開放平臺

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

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在看Apache DolphineScheduler,發現DolphinScheduler在處理任務時,通過先將任務快速的存儲在資料庫中,然後基於對應的Task,將Task放入隊列中,然後將Task進行快速消費的思路。 這種模型在很多框架中,都有體現。 我們知道在Master模塊時處理任務的核心 ...
  • 寫在前面 今天我們來學習一下 Redis 。Redis 是一個高性能的開源記憶體數據存儲系統,支持多種數據結構,如字元串、列表、集合、有序集合和哈希表。 NoSQL 概述 隨著大數據的興起,數據量的暴增,數據類型的豐富,傳統的關係資料庫在應付動態網站,特別是超大規模和高併發的純動態網站時已經顯得力不從 ...
  • 文 / 興業證券股份有限公司 劉洋 石良生 柳君 李致琪 本文來源於網路,如有侵權,請聯繫刪除 任務調度平臺,扮演著自動執行預設任務的重要角色,是業務開展過程中不可或缺的一環。隨著業務規模的不斷擴展,興業證券每日需要進行數以萬計的任務調度,因此,優化和提升任務調度平臺的性能與穩定性至關重要。本文通過 ...
  • ​對各高校即將畢業的學子來說,畢業設計算是在大學里的最後一個大作業。特別是軟體、電腦、電子等相關專業,畢業設計非常講究實操,往往要求實現一個實用的、可用的、易用的軟體系統或手機APP。 不管是軟體還是APP,都要通過編程來實現。對於編程類的畢業設計,既有圖書館管理系統這樣萬年不變的增刪改查軟體,也 ...
  • 寫在前面:本文所述未必符合當前最新情形(包括藍牙技術發展、微信小程式介面迭代等)。 微信小程式為藍牙操作提供了很多介面,但在實際開發過程中,會發現隱藏了不少坑。目前主流藍牙應用都是基於低功耗藍牙(BLE)的,本文介紹相關的幾個基礎介面,並對其進行封裝,便於業務層調用。 藍牙發展 在開發藍牙應用程式之 ...
  • 問題描述 最近發現Flutter中引入像素較大的靜態圖片或者字體導致調試或者打包之後在高刷手機上幀率只有60的問題。 測試設備為小米13,可在開發者選項中直接打開幀率顯示, 也可使用statsfl插件顯示幀率 StatsFl( maxFps: 120, // Support custom FPS t ...
  • 在 C 語言中,記憶體分配主要分為以下幾個區域: 一、棧(Stack) 存儲內容: 局部變數:在函數內部聲明的變數,包括自動變數和函數參數。 函數調用信息:當函數被調用時,會在棧上分配空間來存儲函數的返回地址、參數和局部變數。 特點: 記憶體由編譯器自動管理,分配和釋放非常高效。 空間相對較小,一般幾兆 ...
  • 【HM】華為鴻蒙高級認證資料 目錄【HM】華為鴻蒙高級認證資料判斷題單選題多選題其它 判斷題 【判斷題】每調用一次router.pushUrl()方法,預設情況下,頁面棧數量會加1,頁面棧支持的最大頁面數量為32。正確(True) 【判斷題】首選項preferences是以Key-Value形式存儲 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...