第8章_HarmonyOs开发图解 剪贴板

第8章 HarmonyOs开发图解 剪贴板

HarmonyOS 学习系统 | 阶段二:进阶实战期 建议学习时长:1 周


学习目标

序号 能力
1 掌握 SystemPasteboard 和 PasteData 的使用方法
2 能实现文本复制、粘贴和剪贴板监听功能
3 理解剪贴板的权限限制和大小限制

内容讲解

8.1 剪贴板 API

社区大门口有一块便签板(系统剪贴板)。你在便签板上贴了一张写着"张三 电话 138xxxx"的便签。不管你是谁(哪个应用),只要走到便签板前(应用获得前台焦点),就能看到最新的便签内容。新的便签会覆盖旧的,便签板上的内容不会因为你离开就消失。

HarmonyOS 的 SystemPasteboard 提供了系统剪贴板操作接口,PasteData 是剪贴板数据的载体。

获取剪贴板对象
java 复制代码
// 获取系统剪贴板实例
SystemPasteboard pasteboard = SystemPasteboard.getSystemPasteboard(this);
写入剪贴板
java 复制代码
// 创建纯文本数据
PasteData pasteData = PasteData.createPlainTextData("Hello HarmonyOS!");
// 写入剪贴板
pasteboard.setPasteData(pasteData);

PasteData 支持多种数据类型:

创建方法 数据类型 说明
createPlainTextData() 纯文本 最常用的类型
createHtmlData() HTML 文本 保留富文本格式
createUriData() URI 数据 传递链接或文件路径
createIntentData() Intent 数据 传递 Intent 对象
createMimeData() MIME 类型 自定义 MIME 类型数据
读取剪贴板
java 复制代码
// 检查剪贴板是否有数据
if (pasteboard.hasPasteData()) {
    // 获取剪贴板数据
    PasteData data = pasteboard.getPasteData();
    // 获取主文本
    String text = data.getPrimaryText();
    // 获取 HTML 文本
    String html = data.getPrimaryHtml();
    // 获取 URI
    Uri uri = data.getPrimaryUri();
    // 使用数据...
}
清除剪贴板
java 复制代码
// 清除剪贴板内容
pasteboard.clearPasteData();

8.2 剪贴板变化监听

SystemPasteboard 支持监听剪贴板内容变化:

java 复制代码
// 添加监听器
pasteboard.addPasteDataChangedListener(new IPasteDataChangedListener() {
    @Override
    public void onChanged() {
        HiLog.info(TAG, "剪贴板内容发生了变化");
        // 获取最新内容
        if (pasteboard.hasPasteData()) {
            String newText = pasteboard.getPasteData().getPrimaryText();
            HiLog.info(TAG, "新内容: " + newText);
        }
    }
});

// 移除监听器
pasteboard.removePasteDataChangedListener(listener);

8.3 实战要点

剪贴板的权限限制

只有前台获得焦点的应用才有读取剪贴板的权限(系统默认输入法除外)。这意味着后台服务无法直接读取剪贴板内容。

剪贴板的大小限制

剪贴板单次传递内容不能超过 500KB。如果需要传递大数据量,应使用文件或分布式数据管理来实现。

剪贴板的覆盖机制

每次调用 setPasteData() 都会覆盖之前的剪贴板内容。系统剪贴板是全局唯一的,所有应用共享同一个剪贴板。

8.4 综合实战:剪贴板工具页面

下面是一个完整的剪贴板工具页面实现,包含复制、粘贴和监听功能:

java 复制代码
public class ClipboardSlice extends AbilitySlice {
    private static final HiLogLabel TAG = new HiLogLabel(0, 0, "ClipboardSlice");
    private SystemPasteboard pasteboard;
    private Text tvPasteContent;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_clipboard);

        pasteboard = SystemPasteboard.getSystemPasteboard(this);
        tvPasteContent = (Text) findComponentById(ResourceTable.Id_tv_paste_content);

        Button btnCopy = (Button) findComponentById(ResourceTable.Id_btn_copy);
        Button btnPaste = (Button) findComponentById(ResourceTable.Id_btn_paste);
        Button btnClear = (Button) findComponentById(ResourceTable.Id_btn_clear);

        // 复制按钮
        btnCopy.setClickedListener(component -> {
            TextField tfInput = (TextField) findComponentById(
                ResourceTable.Id_tf_input);
            String text = tfInput.getText();
            if (!text.isEmpty()) {
                PasteData data = PasteData.createPlainTextData(text);
                pasteboard.setPasteData(data);
                new ToastDialog(getContext())
                    .setText("已复制到剪贴板")
                    .show();
            }
        });

        // 粘贴按钮
        btnPaste.setClickedListener(component -> {
            if (pasteboard.hasPasteData()) {
                PasteData data = pasteboard.getPasteData();
                String text = (data.getPrimaryText() != null)
                    ? data.getPrimaryText().toString() : "无文本内容";
                tvPasteContent.setText("剪贴板内容: " + text);
            } else {
                tvPasteContent.setText("剪贴板为空");
            }
        });

        // 清除按钮
        btnClear.setClickedListener(component -> {
            pasteboard.clearPasteData();
            tvPasteContent.setText("剪贴板已清除");
        });

        // 添加剪贴板变化监听
        pasteboard.addPasteDataChangedListener(() -> {
            getUITaskDispatcher().asyncDispatch(() -> {
                if (pasteboard.hasPasteData()) {
                    PasteData data = pasteboard.getPasteData();
                    String newText = (data.getPrimaryText() != null)
                        ? data.getPrimaryText().toString() : "非文本";
                    tvPasteContent.setText("监听到变化: " + newText);
                }
            });
        });
    }

    @Override
    public void onStop() {
        // 移除监听,防止内存泄漏
        pasteboard.removePasteDataChangedListener(null);
        super.onStop();
    }
}

8.5 剪贴板安全注意事项

  • 敏感数据:不要将密码、Token 等敏感信息写入剪贴板,任何前台应用都可以读取
  • 及时清除 :使用完剪贴板后,建议调用 clearPasteData() 清除内容
  • 监听器泄漏 :在 onStop()onDestroy() 中务必移除监听器
  • 线程安全 :剪贴板变化监听回调在非 UI 线程,更新 UI 需要通过 getUITaskDispatcher()

代码速查卡

API 功能 示例
SystemPasteboard.getSystemPasteboard() 获取剪贴板实例 SystemPasteboard.getSystemPasteboard(this)
PasteData.createPlainTextData() 创建纯文本数据 PasteData.createPlainTextData("text")
setPasteData() 写入剪贴板 pasteboard.setPasteData(pasteData)
getPasteData() 读取剪贴板 PasteData data = pasteboard.getPasteData()
hasPasteData() 检查是否有数据 pasteboard.hasPasteData()
clearPasteData() 清除剪贴板 pasteboard.clearPasteData()
addPasteDataChangedListener() 添加变化监听 pasteboard.addPasteDataChangedListener(listener)
removePasteDataChangedListener() 移除变化监听 pasteboard.removePasteDataChangedListener(listener)

与 Android/iOS 对比

特性 HarmonyOS Android iOS
剪贴板管理类 SystemPasteboard ClipboardManager UIPasteboard.general
数据类型 文本/HTML/URI/Intent 文本/URI/Intent 文本/URL/图像/颜色
大小限制 500KB 无硬性限制 无硬性限制
读取权限 前台聚焦应用 所有应用 前台应用
变化监听 addPasteDataChangedListener addPrimaryClipChangedListener 无原生支持
创建数据 PasteData ClipData UIPasteboard 数据

⚠️ 踩坑回忆录

做剪贴板功能时踩了一个大坑:我写了一个后台服务定时读取剪贴板内容,结果发现怎么都读不到。后来才知道:只有前台获得焦点的应用才有读取剪贴板的权限(系统默认输入法除外)。另外,剪贴板单次传递内容不能超过 500KB,大数据量还是得用文件或分布式数据管理。

还有一个容易忽略的问题:SystemPasteboard.getSystemPasteboard(this) 中的 this 参数是 Context,如果你在非 UI 组件中调用(比如工具类),需要传入正确的 Context,否则会返回一个无效的剪贴板实例。


必做实操任务

序号 任务 难度
1 实现一个"复制文本到剪贴板"的按钮功能 ★☆☆
2 实现从剪贴板读取文本并显示的粘贴功能 ★☆☆
3 添加剪贴板变化监听器,实时显示剪贴板内容变化 ★★☆
4 尝试写入不同类型的数据(文本、HTML、URI)并分别读取 ★★☆
5 实现一个简易的剪贴板管理工具,显示剪贴板历史记录 ★★★

学习检查清单

  • 能说出 SystemPasteboard 和 PasteData 的关系
  • 能实现文本的复制和粘贴
  • 理解剪贴板的权限限制
  • 知道剪贴板的大小限制(500KB)
  • 能实现剪贴板变化监听
  • 了解 PasteData 支持的数据类型
  • 知道什么时候应该清除剪贴板

进阶方向

  • 实现剪贴板与分布式数据管理结合的跨设备剪贴板
  • 了解系统输入法对剪贴板的特殊权限
  • 学习在 Service 中无法读取剪贴板的替代方案

相关推荐
森林的尽头是阳光2 小时前
tree回显问题
javascript·vue.js·elementui
qetfw4 小时前
MWU:Vue 3 + FastAPI 的 MaaFramework 跨平台 WebUI 源码
前端·vue.js·python·fastapi·开源项目·效率工具
mfxcyh4 小时前
Vue3+Ant Design Vue 实现手动异步文件上传(含大小校验、弹窗上传)
前端·javascript·vue.js
meilindehuzi_a4 小时前
Vue3进阶基础:指令修饰符、v-model表单绑定、动态样式、计算属性与侦听器实战
前端·javascript·vue.js
csdn2015_4 小时前
vue 前端运行命令
前端·javascript·vue.js
Cobyte4 小时前
根据浏览器解析 HTML 的规范实现 HTML 解析器
前端·javascript·vue.js
用户83134859306985 小时前
Cesium 实现行政区反向遮罩镂空效果(自定义暗色蒙层+矢量/影像底图切换)
vue.js·webgl·cesium
张人玉6 小时前
基于 Vue 3 + ECharts + Express + SQLite 构建的鞋类零售数据分析与毛利预测平台——基于深度学习的鞋类销售数据分析系统
vue.js·sqlite·echarts·express
独泪了无痕16 小时前
Vue3 Hooks使用实战解析
前端·vue.js