Android应用中基于IAM认证的AWS AppSync订阅异常问题排查
我之前做类似的实时位置共享功能时也踩过这个坑——控制台订阅正常,但App里收不到更新,大概率是客户端配置、权限或订阅逻辑的细节没处理好,给你整理几个排查方向:
1. 检查IAM权限是否覆盖订阅操作
控制台用的是管理员权限,但App里的IAM用户/角色可能没配置订阅权限。确保你的IAM政策包含以下内容:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "appsync:Subscribe", "Resource": "arn:aws:appsync:你的区域:你的账号ID:apis/你的AppSyncID/subscriptions/你的订阅名称" }, // 别忘了给Mutation权限(订阅依赖数据源变更触发) { "Effect": "Allow", "Action": "appsync:Mutation", "Resource": "arn:aws:appsync:你的区域:你的账号ID:apis/你的AppSyncID/mutations/你的位置更新Mutation名称" } ] }
同时确认App里的Access Key/Secret对应的IAM用户已经关联了这个政策。
2. 验证订阅的注册时机与生命周期处理
Android界面的生命周期很容易影响订阅状态:比如在onCreate注册订阅,但屏幕旋转后界面重建,订阅没重新注册;或者onPause时取消了订阅,但onResume没重启。参考这个正确的处理逻辑:
private var locationSubscription: AWSAppSyncSubscriptionWatcher<LocationUpdateSubscription>? = null override fun onResume() { super.onResume() startLocationSubscription() } override fun onPause() { super.onPause() locationSubscription?.cancel() locationSubscription = null } private fun startLocationSubscription() { val subscription = LocationUpdateSubscription.builder().build() locationSubscription = appSyncClient.subscribe(subscription) .subscribe({ response -> // 收到位置更新后切到主线程更新地图 val newLocation = response.data()?.locationUpdate runOnUiThread { // 更新Google Map上的标记 } }, { error -> Log.e("LocationSync", "订阅失败: ${error.message}") }) }
另外要保证appSyncClient是全局单例,别每次创建新实例。
3. 检查订阅的过滤条件是否正确
如果你的订阅加了过滤逻辑,比如只接收其他用户的位置,要确认参数传递是否正确。比如订阅定义是:
subscription SubscribeLocation($currentUserId: ID!) { subscribeLocation(filter: { userId: { ne: $currentUserId } }) { lat lng userId } }
那用户B调用订阅时必须传入自己的userId,否则过滤条件会失效,收不到用户A的位置。如果不小心把ne写成eq,就只会收到自己的位置更新。
4. 确认AppSync客户端的实时配置
新版AppSync依赖WebSocket实现订阅,要确保客户端初始化正确:
val appSyncClient = AWSAppSyncClient.builder() .context(applicationContext) .apiUrl("你的AppSync API地址") .credentialsProvider(AWSMobileClient.getInstance()) // 或自定义IAM凭证提供者 .region(Region.getRegion("你的AWS区域")) .build()
同时检查AndroidManifest里的权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Android 12+如果需要后台接收订阅,还要申请POST_NOTIFICATIONS权限,避免系统杀死WebSocket连接。
5. 验证Mutation是否成功触发订阅
用户A发送位置的Mutation有没有成功写入数据源?去AppSync控制台的Logs里查看Mutation执行日志,确认数据已经正确写入。如果Mutation失败(比如数据源权限不足、字段不匹配),订阅是不会被触发的。另外要确认订阅的触发器和Mutation名称对应正确。
内容的提问来源于stack exchange,提问作者sargentin

