TelephonyManager(電話マネージャー)


このセクションの紹介:

この章は、Android の基本的な入門チュートリアルの最終章であり、主に散在するいくつかの知識ポイントといくつかの省略について説明します。 ナレッジ ポイントを補足するために、これらの散在するナレッジ ポイントには、このセクションの電話マネージャーや SMS マネージャーなどのさまざまなシステム サービスの使用が含まれます。 バイブ、目覚まし時計、壁紙など、センサーなど!それはめちゃくちゃです!さて、このセクションで学ぶことは何ですか 名前が示すように、これは TelephonyManager です。携帯電話の通話ステータスを管理し、電話情報 (デバイス情報、SIM カード情報、および ネットワーク情報)、電話の状態(通話状態サービス状態、信号強度状態など)を聞いて、電話ダイヤラに電話して電話をかけることができます。 早速、このセクションを始めましょう~

公式 API:TelephonyManager


1. TelephonyManager のサービス オブジェクトを取得します

TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);


2使用例


1) ダイヤラーに電話して電話番号をダイヤルします

Uri uri=Uri.parse("tel:"+电话号码);    
Intent intent=new Intent(Intent.ACTION_DIAL,uri);    
startActivity(intent);

2) Simカード情報とネットワーク情報を取得します

レンダリングの実行:

1.png

実装コード:

レイアウトファイル:activity_main .xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_phone1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone6"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone7"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_phone8"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp" />

    <TextView
        android:id="@+id/tv_phone9"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp" /></LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private TextView tv_phone1;
    private TextView tv_phone2;
    private TextView tv_phone3;
    private TextView tv_phone4;
    private TextView tv_phone5;
    private TextView tv_phone6;
    private TextView tv_phone7;
    private TextView tv_phone8;
    private TextView tv_phone9;
    private TelephonyManager tManager;
    private String[] phoneType = {"未知","2G","3G","4G"};
    private String[] simState = {"状态未知","无SIM卡","被PIN加锁","被PUK加锁",
            "被NetWork PIN加锁","已准备好"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //①获得系统提供的TelphonyManager对象的实例
        tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        bindViews();
    }

    private void bindViews() {
        tv_phone1 = (TextView) findViewById(R.id.tv_phone1);
        tv_phone2 = (TextView) findViewById(R.id.tv_phone2);
        tv_phone3 = (TextView) findViewById(R.id.tv_phone3);
        tv_phone4 = (TextView) findViewById(R.id.tv_phone4);
        tv_phone5 = (TextView) findViewById(R.id.tv_phone5);
        tv_phone6 = (TextView) findViewById(R.id.tv_phone6);
        tv_phone7 = (TextView) findViewById(R.id.tv_phone7);
        tv_phone8 = (TextView) findViewById(R.id.tv_phone8);
        tv_phone9 = (TextView) findViewById(R.id.tv_phone9);

        tv_phone1.setText("设备编号:" + tManager.getDeviceId());
        tv_phone2.setText("软件版本:" + (tManager.getDeviceSoftwareVersion()!= null?
                tManager.getDeviceSoftwareVersion():"未知"));
        tv_phone3.setText("运营商代号:" + tManager.getNetworkOperator());
        tv_phone4.setText("运营商名称:" + tManager.getNetworkOperatorName());
        tv_phone5.setText("网络类型:" + phoneType[tManager.getPhoneType()]);
        tv_phone6.setText("设备当前位置:" + (tManager.getCellLocation() != null ? tManager
                .getCellLocation().toString() : "未知位置"));
        tv_phone7.setText("SIM卡的国别:" + tManager.getSimCountryIso());
        tv_phone8.setText("SIM卡序列号:" + tManager.getSimSerialNumber());
        tv_phone9.setText("SIM卡状态:" + simState[tManager.getSimState()]);
    }
}

ちなみに、AndroidManifest.xmlに権限を追加することを忘れないでください。

<!-- 添加访问手机位置的权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 添加访问手机状态的权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

ちなみに、通常の 2G、3G、4G ではなくネットワーク標準を取得したい場合は、TelephonyManager クラスのソース コードにアクセスできます:

2.png

さまざまなネットワークに基づいて判断できます。この networkType Standard の値、たとえば networkType == 1 の場合 それは GPRS 形式です~ そして、この networkType の値は

3.png

、つまりこの getNetworkType() メソッドを通じて取得できます。上のように配列をリストして使用するのはとても簡単です。 添字が異なれば、異なる値が表示されます。 ちなみに、文字列配列には Sim カードのステータスと値もあります。ソースコードで確認できます:

4.png

その他は自分で調べることができます~


3) 信号強度を取得します。携帯電話

ネットワーク信号 強度の単位は dBm (ミリワット デシベル) で、通常は負の数で表されます。通常の携帯電話の信号範囲は -110dBm です。 (不良) と -50dBm (良好) の間で、-50dBm より小さい場合は、n5 ディスプレイなどの基地局の近くに立っていることを意味します。 ナンソフトビルが隣にあり、上に基地局があるため、信号強度は-51dBm、場合によっては-59dBmです...

さらに、2G、3G、および 4G で信号強度を取得する方法は、PhoneStateListener の onSignalStrengthsChanged() をオーバーライドすることです。 このイベントは、信号強度が変化したときにトリガーされます。このイベントで信号強度を取得できます。

携帯電話で信号強度を取得するコード例:

dBm =-113+2*asuこれは固定式です、asu (独立信号ユニット)

オペレーションレンダリング:

5.png

実装コード:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private TextView tv_rssi;
    private MyPhoneStateListener mpsListener;
    private TelephonyManager tManager;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tManager = ((TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE));
        tv_rssi = (TextView) findViewById(R.id.tv_rssi);
        mpsListener  = new MyPhoneStateListener();
        tManager.listen(mpsListener,290);
    }

    private class MyPhoneStateListener extends PhoneStateListener {
        private int asu = 0,lastSignal = 0;
        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            asu = signalStrength.getGsmSignalStrength();
            lastSignal = -113 + 2 * asu;
            tv_rssi.setText("当前手机的信号强度:" + lastSignal + " dBm" );
            super.onSignalStrengthsChanged(signalStrength);
        }
    }
}

なお、筆者のカードは全てモバイルカードなのでチャイナユニコムやテレコムについては分かりませんが、ソースからはこんな感じのAPIがいくつかありましたコード:

  • getEvdoDbm() : Telecom 3G
  • getCdmaDbm(): China Unicom 3G
  • getLteDbm(): 4G

信号強度を調整できます。条件がある場合は試してみてください~

また、権限を追加することを忘れないでください!

<!-- 添加访问手机状态的权限 -->
 <uses-permission android:name="android.permission.READ_PHONE_STATE"/>

4) 携帯電話のすべての着信を監視します

監視された通話記録の結果は、さまざまな方法で取得できます。ここで使用されるのは、通話記録をファイルに書き込むことです。 また、テキスト メッセージの形式で送信したり、特定のプラットフォームにアップロードしたりすることもできます。もちろん、通信記録がそれほど多くない場合は、テキスト メッセージを使用することもできます。 もっとたくさんあると、他の人が見つけやすくなります。さらに、ここではサービスの代わりにアクティビティが使用されています。これは、このアクティビティを開くことを意味します。 通常、必要な処理はバックグラウンドで実行する必要があるため、必要に応じてサービスを作成しません。 自分で変更して、ブート時にサービスを開始することができます。

コード分析

は、実際には、TelephonyManager の通話ステータス リスナー

PhoneStateListener を書き換えて、TelephonyManager を呼び出すだけです。 .listen() メソッド 電話の着信を監視し、 プログラムは発信者番号をファイルに記録します。

実装コード:

MainActivity.java:

public class MainActivity extends Activity  
{  
    TelephonyManager tManager;  
  
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        // 取得TelephonyManager对象  
        tManager = (TelephonyManager)   
            getSystemService(Context.TELEPHONY_SERVICE);  
        // 创建一个通话状态监听器  
        PhoneStateListener listener = new PhoneStateListener()  
        {  
            @Override  
            public void onCallStateChanged(int state, String number)  
            {  
                switch (state)  
                {  
                // 无任何状态  
                    case TelephonyManager.CALL_STATE_IDLE:  
                        break;  
                    case TelephonyManager.CALL_STATE_OFFHOOK:  
                        break;  
                    // 来电铃响时  
                    case TelephonyManager.CALL_STATE_RINGING:  
                        OutputStream os = null;  
                        try  
                        {  
                            os = openFileOutput("phoneList", MODE_APPEND);  
                        }  
                        catch (FileNotFoundException e)  
                        {  
                            e.printStackTrace();  
                        }  
                        PrintStream ps = new PrintStream(os);  
                        // 将来电号码记录到文件中  
                        ps.println(new Date() + " 来电:" + number);  
                        ps.close();  
                        break;  
                    default:  
                        break;  
                }  
                super.onCallStateChanged(state, number);  
            }  
        };  
        // 监听电话通话状态的改变  
        tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);  
    }  
}

実行結果:

注意! 別の電話を使用して電話をかけると、DDMS を開くことができます。ファイルエクスプローラーアプリケーション パッケージ名に対応するファイル ディレクトリにphoneList ファイルが表示されます。これをコンピュータにエクスポートして開くことができます。ファイルのおおよその内容は次のとおりです。

THR Oct 30 12:05:48 GMT 電話: 137xxxxxxx

ちなみに、権限を忘れないでください。

<!-- 授予该应用读取通话状态的权限 -->  
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>


5) ブラックリストの電話は自動的に切れます

いわゆるブラックリストとは、いくつかの電話番号をコレクションに追加するもので、電話がこれらの電話を受けると直接切れます。 ただし、Android には電話を切るための API が提供されていないため、AIDL を介してサービス内の API を呼び出す必要があります。 電話を切ることを実現しましょう!

最初のステップは、Android ソース コード内の次の 2 つのファイルを src の下の対応する場所にコピーすることです。 com.android.internal.telephony パッケージの下の ITelephony.aidl android.telephony パッケージの下の

対応するパッケージを作成するには、上記のパッケージの下に aidl ファイルを置くだけです。 その後、通話を切るには ITelephony の endCall に電話するだけです

ここで提供されるのは、番号を入力してブロック ボタンをクリックした後、この時点でブロックされた通話が着信した場合の単純な傍受です。 直接ハングアップします。コードは比較的簡単です。使用するシミュレーターは Genymotion なので、デモは行いません。 プログラム実行後のスクリーンショット!

MainActivity.java

:

public class MainActivity extends Activity {  
  
    private TelephonyManager tManager;  
    private PhoneStateListener pListener;  
    private String number;  
    private EditText locknum;  
    private Button btnlock;  
      
    public class PhonecallListener extends PhoneStateListener  
    {  
        @Override  
        public void onCallStateChanged(int state, String incomingNumber) {  
            switch(state)  
            {  
            case TelephonyManager.CALL_STATE_IDLE:break;  
            case TelephonyManager.CALL_STATE_OFFHOOK:break;  
            //当有电话拨入时  
            case TelephonyManager.CALL_STATE_RINGING:  
                if(isBlock(incomingNumber))  
                {  
                    try  
                    {  
                        Method method = Class.forName("android.os.ServiceManager")  
                                .getMethod("getService", String.class);  
                        // 获取远程TELEPHONY_SERVICE的IBinder对象的代理  
                        IBinder binder = (IBinder) method.invoke(null,  
                            new Object[] { TELEPHONY_SERVICE });  
                        // 将IBinder对象的代理转换为ITelephony对象  
                        ITelephony telephony = ITelephony.Stub.asInterface(binder);  
                        // 挂断电话  
                        telephony.endCall();  
                    }catch(Exception e){e.printStackTrace();}  
                }  
                break;  
            }  
            super.onCallStateChanged(state, incomingNumber);  
        }  
    }  
      
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
          
        locknum = (EditText) findViewById(R.id.locknum);  
        btnlock = (Button) findViewById(R.id.btnlock);  
          
        //获取系统的TelephonyManager管理器  
        tManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);  
        pListener = new PhoneStateListener();  
        tManager.listen(pListener, PhoneStateListener.LISTEN_CALL_STATE);  
          
        btnlock.setOnClickListener(new OnClickListener() {  
              
            @Override  
            public void onClick(View v) {  
                number = locknum.getText().toString();                
            }  
        });  
          
    }  
      
    public boolean isBlock(String phone)  
    {  
        if(phone.equals(number))return true;  
        return false;  
    }  
}

Permissions, Permissions, Permissions:

<!-- 授予该应用控制通话的权限 -->  
<uses-permission android:name="android.permission.CALL_PHONE" />    
<!-- 授予该应用读取通话状态的权限 -->  
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

さらに、関連するプロパティとメソッドの中国語版も参照できます: Android 携帯情報関連 API

3. このセクションのサンプル コードをダウンロードします


TelephonyManagerDemo.zip

TelephonyManagerDemo2.zip

Blacklist Interception Demo.zip

このセクションの概要:


さて、これこのセクションは TelephonyManager (電話管理者の学習はこれで終わりです) に関するものであり、取り上げるべきでした。 開発要件のほとんどは満たされています。不足しているものがあれば、遠慮なく指摘してください~

ありがとうございます~