ClipboardManager 抛出以下错误:Can't create handler inside thread that has not called Looper.prepare() usin
Posted
技术标签:
【中文标题】ClipboardManager 抛出以下错误:Can\'t create handler inside thread that has not called Looper.prepare() using WorkManager【英文标题】:ClipboardManager throws the following error: Can't create handler inside thread that has not called Looper.prepare() using WorkManagerClipboardManager 抛出以下错误:Can't create handler inside thread that has not called Looper.prepare() using WorkManager 【发布时间】:2019-08-28 15:08:14 【问题描述】:我正在创建一个应用程序,用户可以在其中将文本复制到剪贴板 30 秒。 30 秒后需要从剪贴板中删除文本,即使应用程序已关闭 在我的主要活动中,我有以下代码:
OneTimeWorkRequest worker = new OneTimeWorkRequest.Builder(clipboardWorker.class)
.setInitialDelay(30, TimeUnit.SECONDS).build();
WorkManager.getInstance().enqueue(worker);
clipboardWorker 如下所示:
public class clipboardWorker extends Worker
private static final String TAG = "clipboardWorker";
public clipboardWorker(@NonNull Context context, @NonNull WorkerParameters workerParams)
super(context, workerParams);
@NonNull
@Override
public Result doWork()
ClipboardManager clipboardManager = (ClipboardManager) getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("clp", "");
clipboardManager.setPrimaryClip(clip);
return Result.success();
这适用于 android 版本 28,但在 27 上会引发以下错误:
原因:java.lang.RuntimeException: Can't create handler inside the thread that has not called Looper.prepare()
这是堆栈跟踪:
2019-04-07 11:41:15.948 18924-18944/com.example.clipboard E/WM-WorkerWrapper: Work [ id=fa06342b-0130-4562-b323-5871ea0e67fb, tags= com.example.clipboard.clipboardWorker ] failed because it threw an exception/error
java.util.concurrent.ExecutionException: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at androidx.work.impl.utils.futures.AbstractFuture.getDoneValue(AbstractFuture.java:516)
at androidx.work.impl.utils.futures.AbstractFuture.get(AbstractFuture.java:475)
at androidx.work.impl.WorkerWrapper$2.run(WorkerWrapper.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:204)
at android.os.Handler.<init>(Handler.java:118)
at android.content.ClipboardManager$2.<init>(ClipboardManager.java:62)
at android.content.ClipboardManager.<init>(ClipboardManager.java:62)
at android.app.SystemServiceRegistry$11.createService(SystemServiceRegistry.java:254)
at android.app.SystemServiceRegistry$11.createService(SystemServiceRegistry.java:252)
at android.app.SystemServiceRegistry$CachedServiceFetcher.getService(SystemServiceRegistry.java:962)
at android.app.SystemServiceRegistry.getSystemService(SystemServiceRegistry.java:914)
at android.app.ContextImpl.getSystemService(ContextImpl.java:1667)
at android.content.ContextWrapper.getSystemService(ContextWrapper.java:714)
at com.example.clipboard.clipboardWorker.doWork(clipboardWorker.java:26)
at androidx.work.Worker$1.run(Worker.java:85)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
这里抛出错误:
ClipboardManager clipboardManager = (ClipboardManager) getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
以下是 gradle 插件:
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.work:work-runtime:2.0.0'
【问题讨论】:
嗯,是的,你是对的。在 API 级别 28 之前,ClipboardManager
在字段初始化程序中实例化 Handler
,这就是当您尝试在 doWork()
中获取该服务时抛出的原因。从 28 日起,它通过其构造函数传递了一个 Handler
。尝试将clipboardManager
设为一个字段——例如private ClipboardManager clipboardManager;
——并在super
调用之后进入clipboardWorker
的构造函数——clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
。
我的意思是,像这样:drive.google.com/file/d/1Rh6nH4AzyEI_2f1rhmauwHBKWbrog2c2/…。抱歉,我试图在我的评论中缩写一些东西,结果让人困惑。
嗨,迈克,感谢您的回答。我已经像您一样更改了代码,但似乎错误仍然存在。
好的,我不确定Worker
s 是否在主线程上实例化。显然,他们不是。再次检查该链接,然后尝试。
它有效,谢谢。
【参考方案1】:
那是因为 WorkManager Api 的 Worker 类在后台线程上运行,
在 Worker 类中,您可以尝试声明一个附加到主线程的处理程序:
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
然后使用 Handler 的 post() 方法运行你的剪贴板代码
【讨论】:
以上是关于ClipboardManager 抛出以下错误:Can't create handler inside thread that has not called Looper.prepare() usin的主要内容,如果未能解决你的问题,请参考以下文章
ClipBoardManager.OnPrimaryClipChangedListener 不工作
C ++错误:抛出'std :: bad_alloc'实例后调用terminate
无法在 ClipboardManager primaryClip 重新分配 Val