diff --git a/ylgamehall/Source/Share/QQShare.swift b/ylgamehall/Source/Share/QQShare.swift index f141ee0..5373dff 100644 --- a/ylgamehall/Source/Share/QQShare.swift +++ b/ylgamehall/Source/Share/QQShare.swift @@ -114,11 +114,15 @@ public final class QQShare: SharePlatform { parts.append("url=\(Self.encode(Self.base64(content.webpageUrl)))") } - // 3. 缩略图 —— app icon 写到 tmp 目录 → previewimageUrl = urlenc(base64("file://")) - // 对齐 msext QQShareManager.m:517-522 saveImageToTempDirectory + base64 - if let thumbPath = Self.writeAppIconToTemp() { - let fileURL = "file://\(thumbPath)" - parts.append("previewimageUrl=\(Self.encode(Self.base64(fileURL)))") + // 3. 缩略图 —— 字段名是 previewimagedata(图像字节 base64),不是 + // msext 写的 previewimageUrl=base64("file://..."): 后者跨 app 沙盒读不到 + // 本地文件(控制台 `unable to make sandbox extension` 即此原因),实测 + // QQ 渲染破图占位。改对齐 QQ Open SDK 的 previewimagedata 字段,把 + // app icon JPEG 字节本身 base64 内联到 URL。 + // iOS openURL URL 长度限制 ~64KB,app icon 60-180px JPEG 0.6 编码后 + // base64 ≈ 5-15KB,余量充足。 + if let thumbBase64 = Self.appIconBase64() { + parts.append("previewimagedata=\(Self.encode(thumbBase64))") } let urlString = "mqqapi://\(host)?\(parts.joined(separator: "&"))" @@ -191,21 +195,14 @@ public final class QQShare: SharePlatform { return top } - // MARK: - 缩略图(app icon → tmp file) + // MARK: - 缩略图(app icon JPEG → base64 内联到 URL) - /// 把 app icon JPEG 写到 NSTemporaryDirectory,返回绝对路径。 - /// 对齐 msext QQShareManager.m:1271-1278 saveImageToTempDirectory: - /// 文件名 qq_share_.jpg,JPEG 0.7 质量。失败返回 nil。 - private static func writeAppIconToTemp() -> String? { - guard let data = appIconImage().jpegData(compressionQuality: 0.7) else { return nil } - let path = NSTemporaryDirectory() + "qq_share_\(UUID().uuidString).jpg" - do { - try data.write(to: URL(fileURLWithPath: path), options: .atomic) - return path - } catch { - log.error("QQShare 写缩略图临时文件失败 \(error.localizedDescription, privacy: .public)") - return nil - } + /// app icon JPEG 0.6 → base64 字符串。QQ Open SDK previewimagedata 字段的值。 + /// 跨 app 沙盒下 file:// 路径不可读(控制台 `sandbox extension`),唯一可 + /// 靠的传递方式是把图像字节直接 base64 编码到 URL 参数里。 + private static func appIconBase64() -> String? { + guard let data = appIconImage().jpegData(compressionQuality: 0.6) else { return nil } + return data.base64EncodedString() } /// app icon UIImage,与 WechatShare.appIconImage() 同源策略