Android:前台服务Task启动Activity后阻塞,如何避免该问题?
问题描述
我用C#/Xamarin开发,在前台服务启动的Task里尝试用以下代码启动Activity:
new Android.OS.Handler( Looper.MainLooper ).Post( new Java.Lang.Runnable( ( ) => { Intent i = PackageManager.GetLaunchIntentForPackage( appname ); i.AddFlags( (ActivityFlags) 524288 ); // FLAG_ACTIVITY_NEW_TASK StartActivity( i ); }));
不管是同步调用还是上面的异步调用,都会导致Task阻塞,直到退出启动的Activity才恢复运行。就算改用后台服务,其他线程也会被暂停。有意思的是,线程在调用StartActivity()后还能运行约5秒,等新Activity完全初始化后才暂停。
我疑惑是启动Activity的操作导致的阻塞,还是原Service所属Activity不在前台的原因?不过原Activity最小化时线程能正常运行。目前启动应用没问题(知道Android 10+可能无法运行),想问怎么启动Activity才不会阻塞前台服务的Task?
解决方案
给目标Activity配置独立进程:如果目标Activity和前台服务同属一个进程,启动Activity时系统会切换进程优先级到前台,可能导致原服务线程被调度暂停。在AndroidManifest.xml中给目标Activity指定独立进程:
<activity android:name=".TargetActivity" android:process=":separate_process" />新进程运行Activity不会影响原服务Task的执行。
改用PendingIntent启动Activity:避免直接在服务线程中调用
StartActivity,用PendingIntent把启动逻辑交给系统处理,不会阻塞当前线程:var intent = PackageManager.GetLaunchIntentForPackage(appname); intent.AddFlags(ActivityFlags.NewTask); var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.UpdateCurrent); pendingIntent.Send();设置服务Task的长运行优先级:创建Task时指定
TaskCreationOptions.LongRunning,告诉系统该任务是长时间运行的,会分配独立线程,降低被系统暂停的概率:var serviceTask = Task.Factory.StartNew(() => { // 前台服务业务逻辑 }, TaskCreationOptions.LongRunning);排查同步锁问题:检查服务Task代码中是否存在同步锁,确保启动Activity的操作没有持有服务线程的锁资源,避免因锁竞争导致的阻塞。
内容的提问来源于stack exchange,提问作者Matt Ault

