Deep Links 使用说明

CapyPlayer 支持通过深度链接(Deep Links)快速导入资源和 Widget。

URL Scheme

应用使用的 URL Scheme: com.feifeiduck.capyplayer://

支持的深度链接

1. 导入资源(Resource)

通过链接直接打开资源添加页面,并预填充服务器信息。

格式

com.feifeiduck.capyplayer://add-resource?data=<base64_encoded_json>

data 参数是一个 base64url 编码的 JSON 对象,支持以下字段:

字段 类型 说明 示例
serverType string 服务器类型 emby, jellyfin, plex, fnnas
host string 服务器地址 192.168.1.100my-server.com
port number 端口号 8096
username string 用户名(可选) admin
password string 密码(可选) mypassword
https boolean 是否使用 HTTPS truefalse
path string 路径(可选) /emby

JavaScript 示例

// 生成资源导入链接
function generateResourceLink(config) {
  // 构建 JSON 对象
  const params = {
    serverType: config.serverType || 'emby',
    host: config.host,
    port: config.port,
    https: config.https || false
  };

  // 添加可选参数
  if (config.username) params.username = config.username;
  if (config.password) params.password = config.password;
  if (config.path) params.path = config.path;

  // 转换为 JSON 字符串并编码为 base64url
  const jsonString = JSON.stringify(params);
  const base64 = btoa(unescape(encodeURIComponent(jsonString)))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');

  return `com.feifeiduck.capyplayer://add-resource?data=${base64}`;
}

// 使用示例
const link = generateResourceLink({
  serverType: 'emby',
  host: '192.168.1.100',
  port: 8096,
  username: 'admin',
  password: 'pass#word',  // 特殊字符会自动处理
  https: true
});

console.log(link);
// 输出: com.feifeiduck.capyplayer://add-resource?data=eyJzZXJ2ZXJUeXBlIjoiZW1ieSIsImhvc3QiOiIxOTIuMTY4LjEuMTAwIiwicG9ydCI6ODA5NiwidXNlcm5hbWUiOiJhZG1pbiIsInBhc3N3b3JkIjoicGFzcyN3b3JkIiwiaHR0cHMiOnRydWV9

空链接(打开空白添加页面):

com.feifeiduck.capyplayer://add-resource

2. 导入 Widget

通过链接直接打开 Widget 添加页面,并自动加载指定的 Widget URL。

格式

com.feifeiduck.capyplayer://add-widget?data=<base64_encoded_url>

data 参数是 base64url 编码的 Widget manifest URL。

JavaScript 示例

// 生成 Widget 导入链接
function generateWidgetLink(manifestUrl) {
  // 将 URL 编码为 base64url
  const base64 = btoa(manifestUrl)
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');

  return `com.feifeiduck.capyplayer://add-widget?data=${base64}`;
}

// 使用示例
const link = generateWidgetLink('https://example.com/widget/manifest.json#section');

console.log(link);
// 输出: com.feifeiduck.capyplayer://add-widget?data=aHR0cHM6Ly9leGFtcGxlLmNvbS93aWRnZXQvbWFuaWZlc3QuanNvbiNzZWN0aW9u

在网页中使用:

<a href="com.feifeiduck.capyplayer://add-widget?data=aHR0cHM6Ly9leGFtcGxlLmNvbS93aWRnZXQvbWFuaWZlc3QuanNvbg==">
  安装到 CapyPlayer
</a>

空链接(打开空白添加页面):

com.feifeiduck.capyplayer://add-widget

使用场景

场景 1: 服务器管理员分享配置

服务器管理员可以生成包含服务器信息的链接,分享给用户快速添加资源:

const link = generateResourceLink({
  serverType: 'emby',
  host: 'my-server.com',
  port: 8096,
  https: true
});

// 分享链接给用户
console.log('点击链接快速添加服务器:', link);

场景 2: Widget 开发者提供一键安装

Widget 开发者可以在网站上提供一键安装按钮:

<!DOCTYPE html>
<html>
<head>
  <title>我的 Widget</title>
  <script>
    function generateWidgetLink(manifestUrl) {
      const base64 = btoa(manifestUrl)
        .replace(/\+/g, '-')
        .replace(/\//g, '_')
        .replace(/=/g, '');
      return `com.feifeiduck.capyplayer://add-widget?data=${base64}`;
    }

    const manifestUrl = 'https://mywidget.com/manifest.json';
    const installLink = generateWidgetLink(manifestUrl);
  </script>
</head>
<body>
  <h1>我的 Widget</h1>
  <a href="#" onclick="window.location.href=installLink">
    <button>安装到 CapyPlayer</button>
  </a>
</body>
</html>

场景 3: 二维码分享

将深度链接转换为二维码,用户扫码即可快速添加。可以使用任何二维码生成库,例如:

// 使用 qrcode.js 库
const QRCode = require('qrcode');

const link = generateResourceLink({
  serverType: 'jellyfin',
  host: '192.168.1.50',
  port: 8096,
  https: true
});

QRCode.toDataURL(link, (err, url) => {
  console.log('二维码图片:', url);
});

安全注意事项

  1. 密码处理: 虽然支持在 URL 中传递密码,但不建议在公开场合分享包含密码的链接
  2. Base64 不是加密: base64 编码只是为了支持特殊字符(如 #, &, =),不提供安全保护
  3. HTTPS: 建议使用 HTTPS 连接以保护数据传输安全

编码说明

所有参数使用 base64url 编码(RFC 4648),与标准 base64 的区别:

  • 使用 - 替代 +
  • 使用 _ 替代 /
  • 移除末尾的 = 填充字符

JavaScript 转换示例:

// 标准 base64 转 base64url
function toBase64Url(base64) {
  return base64
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '');
}

// base64url 转标准 base64
function fromBase64Url(base64url) {
  let base64 = base64url
    .replace(/-/g, '+')
    .replace(/_/g, '/');

  // 添加填充
  while (base64.length % 4) {
    base64 += '=';
  }

  return base64;
}

测试深度链接

iOS 测试

# 测试资源导入
xcrun simctl openurl booted "com.feifeiduck.capyplayer://add-resource?data=eyJzZXJ2ZXJUeXBlIjoiZW1ieSIsImhvc3QiOiIxOTIuMTY4LjEuMTAwIiwicG9ydCI6ODA5NiwiaHR0cHMiOnRydWV9"

# 测试 Widget 导入
xcrun simctl openurl booted "com.feifeiduck.capyplayer://add-widget?data=aHR0cHM6Ly9leGFtcGxlLmNvbS9tYW5pZmVzdC5qc29u"

Android 测试

# 测试资源导入
adb shell am start -W -a android.intent.action.VIEW -d "com.feifeiduck.capyplayer://add-resource?data=eyJzZXJ2ZXJUeXBlIjoiamVsbHlmaW4iLCJob3N0IjoiMTkyLjE2OC4xLjUwIiwicG9ydCI6ODA5Nn0="

# 测试 Widget 导入
adb shell am start -W -a android.intent.action.VIEW -d "com.feifeiduck.capyplayer://add-widget?data=aHR0cHM6Ly9leGFtcGxlLmNvbS93aWRnZXQvbWFuaWZlc3QuanNvbg=="