背景
有时候我们需要在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);
}
}
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态