Android 监听双卡信号强度(更新到android10

Android 监听双卡信号强度(更新到android10

背景介绍

Android一开始设计并没有考虑双卡的情况,很多APi都是对默认的sim卡做操作,需要监听两张sim卡的信号强度,必须采用一些特殊的方式,比如反射。
该文章基于android10的源代码做分析,对网上一种通过反射改PhoneStateListener中mSubId的方法(点这了解)做了修正,使其适应android10版本

相关Android类

android.telephony.PhoneStateListener
android.telephony.TelephonyManager

代码

Android 10 中在TelePhonymanager中更新了一个createForSubscriptionId(int),我们可以从源代码的头部注释中找到

 * a listener to receive notification of telephony state changes.
 * <p>
 * The returned TelephonyManager will use the default subscription for all calls.
 * To call an API for a specific subscription, use {@link #createForSubscriptionId(int)}. e.g.
 * <code>
 *   telephonyManager = defaultSubTelephonyManager.createForSubscriptionId(subId);
 * </code>
 * <p>

createForSubscriptionId(int)方法参数的int是sim卡的subscription ID,返回一个TelePhonyManager实例,这个实例对应传入参数对应的sim卡,而不再对应默认的sim卡
调用方式如下

TelephonyManager mTM=((TelephonyManager) 
mcontext.getSystemService(Context.TELEPHONY_SERVICE)).createForSubscriptionId(mSubID);
 

如果手机系统是android 10,那么可以直接 mPSL=new PhoneStateListener(),
然后mTM.listen(mPSL, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS |
PhoneStateListener.LISTEN_CELL_INFO | PhoneStateListener.LISTEN_CELL_LOCATION);

相关的使用说明在https://developer.android.google.cn/about/versions/10/non-sdk-q?hl=zh-cn中可以搜到


    Landroid/telephony/PhoneStateListener;-><init>(Ljava/lang/Integer;)V   # alternative: {@link PhoneStateListener()} use default constructor without passing subId. To listen for specific subscription, use {@TelephonyManager#createForSubscriptionId(int subId)} and {@link TelephonyManager#listen(PhoneStateListener psl)};

我们再查看TelePhonyManager源代码给的listen函数

  public void listen(PhoneStateListener listener, int events) {
        if (mContext == null) return;
        try {
            boolean notifyNow = (getITelephony() != null);
            ITelephonyRegistry registry = getTelephonyRegistry();
            if (registry != null) {
                // subId from PhoneStateListener is deprecated Q on forward, use the subId from
                // TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
                int subId = mSubId;
                if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) {
                    // since mSubId in PhoneStateListener is deprecated from Q on forward, this is
                    // the only place to set mSubId and its for "informational" only.
                    //  TODO: remove this once we completely get rid of mSubId in PhoneStateListener
                    listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
                            ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
                } else if (listener.mSubId != null) {
                    subId = listener.mSubId;
                }
                registry.listenForSubscriber(subId, getOpPackageName(),
                        listener.callback, events, notifyNow);
            } else {
                Rlog.w(TAG, "telephony registry not ready.");
            }
        } catch (RemoteException ex) {
            // system process dead
        }
    }

重点看中间有一个if判断,如果手机系统是android10或以上,listener的mSubId就会被telephonymanager中的subId替代,如果手机系统是android10以下,那么telephonymanager的subId就会被listener.mSubId替代。
所以存在这么一种情况,手机系统是android10以下,mTM=createForSubscriptionId(int)传入的是sim卡1的subId,然后listener中的mSubId是默认sim卡2的subId,然后mTM中的subId被listener中的替代。。。这个时候mTM监听的sim卡就不是sim卡1 的信号强度了。。。

所以在手机系统低于android10的时候需要把listener的mSubId也同步修改了,因为PhoneStateListener中的mSubID不是public属性,所以需要用到反射

 private void setListeningSimCard(int subId) {
        try {
            Field field = PhoneStateListener.class.getDeclaredField("mSubId");
            field.setAccessible(true);

//            field.setInt(mPSL,subId);
            field.set(mPSL,new Integer(subId));

        }catch (Exception e){
            e.printStackTrace();
        }

    }

注意:我找过网上许多博客,很多都是使用field.setInt()方法,但是在Android10中mSubId类型由int变成了Integer,所以需要改成field.set() ,希望这个能帮助到你。

最后给一个比较完整的调用的代码,两张不同的sim卡传入不同的subId,并创建对应的mTM和mPSL就可以实现对两张sim卡的同时监听。

TelephonyManager mTM;
PhoneStateListener mPSL;
Context mcontext; // 可以是activity的context
int subId; //从SubscriptionManager中可以拿到双卡对应的subId

mTM=((TelephonyManager) mcontext.getSystemService(Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId);

        mPSL = new PhoneStateListener();
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            setListeningSimCard(subId);
        }
        mTM.listen(mPSL, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CELL_INFO | PhoneStateListener.LISTEN_CELL_LOCATION);
        

参考

https://blog.csdn.net/qq_29333911/article/details/78962907

https://developer.android.google.cn/about/versions/10/non-sdk-q?hl=zh-cn

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android Studio中获取信号强度的代码可以通过使用TelephonyManager类来实现。以下是一个示例代码: ```java import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.telephony.PhoneStateListener; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private TelephonyManager telephonyManager; private MyPhoneStateListener myPhoneStateListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 检查并请求权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE}, 1); } } // 获取TelephonyManager实例 telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); // 创建PhoneStateListener监听器 myPhoneStateListener = new MyPhoneStateListener(); // 注册监听器 telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); } // 自定义PhoneStateListener private class MyPhoneStateListener extends PhoneStateListener { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { super.onSignalStrengthsChanged(signalStrength); // 获取信号强度值 int signalStrengthValue = signalStrength.getGsmSignalStrength(); // 进行相应的处理,例如显示在UI上或者进行其他操作 Toast.makeText(MainActivity.this, "信号强度:" + signalStrengthValue, Toast.LENGTH_SHORT).show(); } } @Override protected void onDestroy() { super.onDestroy(); // 取消监听器的注册 telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_NONE); } } ``` 请注意,为了获取手机信号强度,您需要在AndroidManifest.xml文件中添加相应的权限: ```xml <uses-permission android:name="android.permission.READ_PHONE_STATE" /> ``` 相关问题: 1. 如何在Android Studio中获取手机信号强度? 2. 什么是TelephonyManager类? 3. 如何请求获取读取手机状态的权限? 4. 如何监听手机信号强度的变化?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值