android 获取剪切内容,Android Q 获取剪切板内容
背景
有时候我们需要在app启动时去获取用户复制的内容,这时候需要进行剪切板相关操作,而Android Q开始只有系统默认的输入法应用或者应用处于焦点时才能获取到剪切板的数据,经测试只有targetSdkVersion和设备型号均为Android Q以上时此规则才会生效。
原来获取剪切板的操作如下:
ClipboardManager clipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = clipboardManager.getPrimaryClip();
现在Android Q的api说明如下
/**
* Returns the current primary clip on the clipboard.
*
* If the application is not the default IME or does not have input focus this return
* {@code null}.
*
* @see #setPrimaryClip(ClipData)
*/
public @Nullable ClipData getPrimaryClip(){
try {
return mService.getPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
网上的解决方法一般如下:
@Override
protected void onResume(){
super.onResume();
getWindow().getDecorView().post(new Runnable() {
@Override
public void run(){
//剪切板相关操作
}
});
}
这种解决方式有一些问题,如果该activity有跳转至其他应用的情况,可能当执行这段方法时正好处于未获取焦点状态导致获取失败,另外在有的情况,我们可能没法获取到activity的示例,在一些服务或者android sdk的开发中,并不能知道当前应用是否已经获取到焦点,此时我们可以采取如下做法:获取剪切板数据时采取重试的方式,获取失败后重试三次,第一次等待20ms,第二次等待40ms,第三次等待60ms,然后监听应用启动和从后台切换到前台的情况来执行上述获取剪切板的操作。
示例代码如下:
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
private int count = 0;
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState){
}
@Override
public void onActivityStarted(@NonNull Activity activity){
if (count++ == 0) {
// 应用首次启动或者是从后台切换到前台
ClipUtils.getClipData(getApplicationContext(), new ClipUtils.GetClipCallback() {
@Override
public void execute(String clipData){
}
});
}
}
@Override
public void onActivityResumed(@NonNull final Activity activity){
}
@Override
public void onActivityPaused(@NonNull Activity activity){
}
@Override
public void onActivityStopped(@NonNull Activity activity){
count--;
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState){
}
@Override
public void onActivityDestroyed(@NonNull Activity activity){
}
});public class ClipUtils{
private static final int MAX_RETRY_TIME = 3;
private static final int FIRST_TIME_DELAY = 20;// 首次等待20ms
private static final int DELAY_TIME_ADD = 20; // 每次增加20ms
static class GetFormAndroidQTask implements Runnable{
private int retryTime = 0;
private Handler mHandler;
private Context mContext;
private GetClipCallback mGetClipCallback;
GetFormAndroidQTask(Context context, Handler handler, GetClipCallback getClipCallback) {
mHandler = handler;
mContext = context;
mGetClipCallback = getClipCallback;
}
public void run(){
ClipboardManager clipboardManager = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = clipboardManager != null ? clipboardManager.getPrimaryClip() : null;
if (clipData != null) {
String data = getData(clipboardManager, clipData);
mGetClipCallback.execute(data);
return;
}
retryTime++;
if (retryTime < MAX_RETRY_TIME) {
mHandler.postDelayed(this, FIRST_TIME_DELAY + retryTime * DELAY_TIME_ADD);
}
}
}
public static void getClipData(Context context, GetClipCallback clipCallback){
String data = null;
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clipData = clipboardManager != null ? clipboardManager.getPrimaryClip() : null;
// 如果是android Q执行重试逻辑
if (clipData == null && android.os.Build.VERSION.SDK_INT >= 29) {
Handler handler = new Handler(context.getMainLooper());
handler.postDelayed(new GetFormAndroidQTask(context, handler, clipCallback), FIRST_TIME_DELAY);
return;
}
data = getData(clipboardManager, clipData);
}
} catch (Throwable t) {
t.printStackTrace();
}
clipCallback.execute(data);
}
private static String getData(ClipboardManager clipboardManager, ClipData clipData){
CharSequence data = null;
if (clipData!= null && clipData.getItemCount() > 0) {
data = clipData.getItemAt(0).getText();
}
// 清空剪切板
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, ""));
return data != null ? data.toString() : null;
}
public interface GetClipCallback{
void execute(String clipData);
}
}
android 获取剪切内容,Android Q 获取剪切板内容相关推荐
- C语言学习:除去剪切板内容的换行与回车
前言 我们在复制PDF文件文本内容的时候,常常为文本中多了些换行符而困扰,所以作者特地制作一个程序解决这个问题. 程序说明 作者为博主:余宁C 程序自动将剪切板中的回车或者换行替换为空格,每1s执行一 ...
- Android 10 获取剪切板内容
一般可以放在Activity的onResume中调用如下方法: //获取剪切板内容 private void getClipboardData() {this.getWindow().getDecor ...
- 各系统剪切板内容获取
最近在做UI自动化,出现点击按钮复制文案到剪切板的操作,由于执行机器有mac.win10.liunx,出现不同的兼容问题,简单记录一下 1.常用获取方式 Python xerox模块 import x ...
- python获取剪切板图片_python 获取剪切板内容的两种方法
第一种 # -*- coding: utf-8 -*- # @Time : 2020/3/16 21:26 # @File : get_text_from_cupboard_13.py # @Auth ...
- js获取剪切板内容(企业微信内嵌网页)
js获取剪切板内容 应用场景 剪切板内容获取 腾讯会议获取会议时间.会议链接和会议号 更新========================= 企业微信页面剪切板内容读取 iPhone无法进入页面 零宽 ...
- ios开发读取剪切板的内容_iOS中管理剪切板的UIPasteboard粘贴板类用法详解
一.自带剪切板操作的原生UI控件在iOS的UI系统中,有3个控件自带剪切板操作,分别是UITextField.UITextView与UIWebView.在这些控件的文字交互处进行长按手势可以在屏幕视图 ...
- PyQt5 技术篇-在clipboard.dataChanged.connect()里如何写入剪切板示例演示,pyqt5监听剪切板变动并写入剪切板内容
PyQt5 自带的写入剪切板方法在 clipboard.dataChanged.connect() 里不生效,主要是为了避免死循环. 不过利用其它的写入剪切板方法放在里面就不会有影响了,比如 pype ...
- 计算机关闭系统剪切板上的内容,怎么清空剪切板内容?
当您在使用电脑的"复制"以及"剪切"功能时,windows系统会把"复制"或"剪切"内容暂时存储在内存里,假如暂存的数据 ...
- Win10清空剪切板内容的方法介绍
剪切板是用户最经常使用的系统功能,可以对想要操作的内容进行临时缓存,但是长时间对里面的内容不清理的话,就会造成系统卡顿.下面小编就给大家介绍一下Win10清空剪切板内容的方法. 操作过程: 1.在Wi ...
最新文章
- ios首次加载web_ios加载webview显示进度条OC版
- PowerDesigner 把Comment写到name中 和把name写到Comment中 pd7以后版本可用
- Det3D - 首个通用 3D 目标检测框架
- Oracle DBA手记3:数据库性能优化与内部原理解析
- 环境搭建:通过repo下载gerrit管理的code
- 软件质量特性 McCall软件质量模型
- android无法格式化sd卡,手机sd卡无法格式化怎么回事?手机sd卡无法格式化解决方法...
- base64字符串转换为图片
- php导出doc文件_php生成word文档并下载
- Operations-ansible-01
- idea 查询项目代码行数_idea统计代码行数Statistic的步骤详解
- [打新技巧]打新股产品跷跷板定律
- Manjaro第二天
- java面试170道精讲:留着慢慢看
- Floyd Thomas - Principles of Electric Circuits_ Conventional Current-Pearson (2021) 电路基础书籍推荐
- 服务器摆放需要预留U位么_办公沙发摆放有何讲究?
- IPC、Binder及AIDL原理机制
- 2016全球计算机排名,2016年全球计算机专业最佳大学TOP50新鲜出炉
- GBDT,XGBoost和LightBoost对比
- 8 excel vba 往多行写入数据