Android IntentService中USSD请求无响应问题修复求助
修复你的USSD IntentService问题
看起来你遇到的问题主要是线程阻塞、回调方法未正确重写以及IntentService的使用方式不当导致的。我会一步步帮你修复代码,并解释每个问题点:
主要问题分析
- 工作线程阻塞:你在
onHandleIntent里用while(jobInProgress)循环卡死了IntentService的工作线程,这种阻塞完全没必要——IntentService的设计初衷就是处理完任务后自动销毁,不需要手动循环等待。 - 回调方法未正确重写:你的
MyCallback方法没有加@Override注解,一旦方法签名有细微错误,编译器无法检测,就会导致回调根本不触发,这是你看不到Toast的核心原因之一。 - 不必要的Handler:
sendUssdRequest的第三个Handler参数可以传null,系统会自动用主线程Handler执行回调,不需要手动创建。 - jobInProgress初始值错误:初始设为
true会导致循环直接启动,实际上应该在发起请求前才设为true。
修复后的完整代码
public class MyService extends IntentService { public static boolean jobInProgress = false; private TelephonyManager tm; // IntentService必须显式提供构造函数 public MyService() { super("MyService"); } // 正确实现USSD回调,添加@Override确保重写父类方法 class MyCallback extends TelephonyManager.UssdResponseCallback { private final Context mContext; MyCallback(Context context) { this.mContext = context.getApplicationContext(); // 使用Application Context更稳妥 } @Override public void onReceiveUssdResponse(TelephonyManager telephonyManager, String request, CharSequence response) { super.onReceiveUssdResponse(telephonyManager, request, response); Toast.makeText(mContext, "Response from network is : " + response, Toast.LENGTH_LONG).show(); jobInProgress = false; stopSelf(); // 回调完成后主动停止服务 } @Override public void onReceiveUssdResponseFailed(TelephonyManager telephonyManager, String request, int failureCode) { super.onReceiveUssdResponseFailed(telephonyManager, request, failureCode); Toast.makeText(mContext, "USSD request failed with code " + failureCode, Toast.LENGTH_LONG).show(); jobInProgress = false; stopSelf(); // 请求失败也停止服务 } } @Override public void onCreate() { super.onCreate(); Toast.makeText(this, "Service is created.", Toast.LENGTH_LONG).show(); } @Override public void onDestroy() { super.onDestroy(); Toast.makeText(this, "Service is destroyed", Toast.LENGTH_LONG).show(); } @Override protected void onHandleIntent(@Nullable Intent intent) { doJob(); // 移除阻塞循环,回调触发后会主动停止服务 } private void doJob() { tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); if (tm == null) { Toast.makeText(getApplicationContext(), "TelephonyManager initialization failed", Toast.LENGTH_SHORT).show(); stopSelf(); return; } // 检查权限,API23+必须动态申请CALL_PHONE权限 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { Toast.makeText(getApplicationContext(), "CALL_PHONE permission not granted", Toast.LENGTH_SHORT).show(); stopSelf(); return; } jobInProgress = true; // 第三个参数传null,系统自动使用主线程Handler执行回调 tm.sendUssdRequest("#105*2#", new MyCallback(this), null); } }
额外注意事项
- 动态权限申请:API23及以上系统,启动服务前要先动态申请
CALL_PHONE权限:if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CALL_PHONE}, 100); return; } // 权限通过后再启动服务 startService(new Intent(this, MyService.class)); - Manifest配置:确保在Manifest中注册服务并声明权限:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 可选,用于检测网络状态 --> <application ...> <service android:name=".MyService" /> </application> - 双卡设备适配:如果需要支持双卡,需使用
TelephonyManager.createForSubscriptionId()获取对应卡槽的实例,否则默认使用主卡槽。
修改后,你的服务就能正常发起USSD请求,收到响应或失败时弹出Toast,最后自动停止服务。
内容的提问来源于stack exchange,提问作者tom johnes
相关产品推荐
相关产品推荐

