RxJava2中Listener转Single及Play Services Auth短信监听代码迁移至SmsManager类
解决方案
没问题,我来帮你把这段代码封装到SmsManager类里,同时转换成RxJava2的Single类型。下面是具体的实现步骤和代码示例:
1. 创建封装的SmsManager类
我们会把短信监听的逻辑封装到独立的SmsManager类中,通过手动创建RxJava2 Single的方式,将Google Play Services的回调式Task转换成响应式流。这样既保证了代码的封装性,又能利用RxJava的优势简化线程调度和错误处理。
import android.content.Context import com.google.android.gms.auth.api.phone.SmsRetriever import com.google.android.gms.tasks.OnFailureListener import com.google.android.gms.tasks.OnSuccessListener import io.reactivex.Single import io.reactivex.SingleEmitter import io.reactivex.SingleOnSubscribe class SmsManager(private val appContext: Context) { // 返回Single<Unit>,对应原Task的Void返回值 fun startSmsRetriever(): Single<Unit> { return Single.create(SingleOnSubscribe<Unit> { emitter -> val smsRetrieverClient = SmsRetriever.getClient(appContext) val task = smsRetrieverClient.startSmsRetriever() // 处理Task成功回调 task.addOnSuccessListener(OnSuccessListener<Void> { emitter.onSuccess(Unit) }) // 处理Task失败回调 task.addOnFailureListener(OnFailureListener { exception -> emitter.onError(exception) }) }) } }
2. 使用RxJava Single处理结果
现在你可以在需要调用的地方,轻松使用这个方法,同时借助RxJava的线程调度器来控制执行线程和回调线程:
// 初始化SmsManager(注意传入ApplicationContext,避免内存泄漏) val smsManager = SmsManager(applicationContext) // 调用方法并订阅结果 smsManager.startSmsRetriever() .subscribeOn(io.reactivex.schedulers.Schedulers.io()) // 在IO线程执行请求 .observeOn(io.reactivex.android.schedulers.AndroidSchedulers.mainThread()) // 在主线程处理回调 .subscribe( { // 对应原代码的onSuccess逻辑,这里可以写你的业务操作 // do something }, { error -> // 对应原代码的onFailure逻辑,处理错误 // Handle error } )
可选:使用官方RxJava适配库简化代码
如果你不想手动封装Task,可以使用Google官方提供的rxjava2-google-api-client库,它能直接将Google的Task转换为RxJava流。
首先在你的build.gradle(Module级别)中添加依赖:
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1' // 请使用匹配你的Play Services版本 implementation 'com.google.rxjava:rxjava2-google-api-client:1.1.0'
然后SmsManager的方法可以简化为:
import android.content.Context import com.google.android.gms.auth.api.phone.SmsRetriever import com.google.android.gms.tasks.Tasks import io.reactivex.Single class SmsManager(private val appContext: Context) { fun startSmsRetriever(): Single<Unit> { val smsRetrieverClient = SmsRetriever.getClient(appContext) return Single.fromCallable { // 使用Tasks.await()阻塞当前线程获取结果,所以必须配合subscribeOn切换到非主线程 Tasks.await(smsRetrieverClient.startSmsRetriever()) Unit } } }
重要注意事项
- 记得在
AndroidManifest.xml中添加必要的权限和广播接收器声明,否则SmsRetriever无法正常工作:
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" /> <receiver android:name=".your.package.SmsBroadcastReceiver" // 替换成你的广播接收器类 android:exported="true"> <intent-filter> <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" /> </intent-filter> </receiver>
- 初始化
SmsManager时一定要传入ApplicationContext,而不是Activity或Fragment的上下文,避免内存泄漏。
内容的提问来源于stack exchange,提问作者MichelReap
相关产品推荐
相关产品推荐

