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 카드 정보 및 네트워크 정보 가져오기
렌더링 실행:
구현 코드:
레이아웃 파일: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 클래스의 소스 코드로 이동할 수 있습니다.
다양한 네트워크 기반을 판단할 수 있습니다. 이 networkType 표준의 값(예: networkType == 1인 경우) 그거 GPRS 형식이에요~ 그리고 이 networkType의 값은 getNetworkType() 메소드를 통해 얻을 수 있어요! 좋아요, 위와 같이 배열을 나열한 다음 사용할 수 있습니다. 다른 첨자는 다른 값을 표시합니다! 그런데 문자열 배열에는 Sim 카드 상태와 값도 있습니다. 소스 코드에서 볼 수 있습니다.
다른 것들은 직접 탐색할 수 있습니다~
3) 신호 강도를 확인하세요. 휴대폰
네트워크 신호 강도의 단위는 dBm(밀리와트 데시벨)이며 일반적으로 음수로 표시됩니다. 일반적인 휴대폰 신호 범위는 -110dBm입니다. (나쁨)과 -50dBm(양호) 사이에서 -50dBm보다 작으면 내 n5 디스플레이와 같이 기지국 근처에 서 있다는 의미입니다. 신호 강도는 -51dBm이고 때로는 -59dBm입니다. Nansoft 빌딩이 옆에 있고 위에 기지국이 있기 때문입니다...또한 2G, 3G, 4G에서 신호 강도를 얻는 방법은 PhoneStateListener의 onSignalStrengthsChanged()를 재정의하는 것입니다. 방법, 이 이벤트는 신호 강도가 변경되면 트리거됩니다. 이 이벤트에서 신호 강도를 얻을 수 있습니다.
신호 강도를 얻기 위한 휴대폰의 코드 예:
dBm =-113+2*asu이것은 고정 공식 asu(독립 신호 단위)
작업 렌더링:
구현 코드 :
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가 여럿 보이더군요. code:
- getEvdoDbm() : Telecom 3G
- getCdmaDbm(): China Unicom 3G
- getLteDbm(): 4G
이들은 dBm을 직접 얻을 수 있어야 합니다. 신호 강도를 높일 수 있습니다. 조건이 있으면 한번 해보세요~
그리고 권한 추가도 잊지 마세요!
<!-- 添加访问手机状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
4) 휴대폰의 모든 수신 통화를 모니터링하세요
모니터링된 통화 기록 결과를 다양한 방법으로 얻을 수 있습니다. 여기서 사용되는 것은 통화 기록을 파일에 쓰는 것입니다. 그리고 문자 메시지 형태로 보내거나, 특정 플랫폼에 업로드할 수도 있습니다. 물론, 통신 기록이 많지 않은 경우에는 문자 메시지를 사용할 수도 있습니다. 더 있으면 다른 사람들도 쉽게 찾을 수 있을 거예요! 또한 여기서는 Service 대신 Activity를 사용하는데, 이는 이 Activity를 여는 것을 의미하며, 그래야만 모니터링할 수 있습니다. 일반적으로 우리의 요구사항은 시간 제약으로 인해 백그라운드에서 비밀리에 실행되어야 합니다. 직접 수정하여 부팅과 함께 서비스를 시작할 수 있습니다!
코드 분석 :
실제로는 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 Call : 137xxxxxxx
그런데 권한도 잊지 마세요!
<!-- 授予该应用读取通话状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
5) 블랙리스트 전화는 자동으로 끊어집니다
여기서는 차단된 전화가 오면 번호를 입력하고 차단 버튼을 클릭하면 됩니다. 코드는 비교적 간단합니다. 사용된 시뮬레이터는 Genymotion이므로 설명하지 않겠습니다. 프로그램 실행 후 스크린샷!소위 블랙리스트는 일부 전화번호를 컬렉션에 추가하고, 전화가 이러한 전화를 받으면 바로 끊어지는 것입니다! 하지만 안드로이드에서는 전화를 끊을 수 있는 API를 제공하지 않기 때문에 서비스 내에서 AIDL을 통해 API를 호출해야 합니다. 전화 끊기 달성!
첫 번째 단계는 Android 소스 코드의 다음 두 파일을 src 아래의 해당 위치에 복사하는 것입니다. ITelephony.aidl com.android.internal.telephony 패키지 아래
NeighboringCellInfo.aidlandroid.telephony 패키지 아래
해당 패키지를 생성하려면 위 패키지 아래에aidl 파일을 넣으면 됩니다 !!! 그런 다음 ITelephony의 endCall에 전화하기만 하면 전화를 끊을 수 있습니다.
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" />또한 중국어 버전의 관련 속성 및 메소드를 볼 수 있습니다:
3. 이 섹션에서 샘플 코드를 다운로드하세요
Blacklist Interception Demo.zip
이 섹션 요약:
알았어, 이거 섹션은 TelephonyManager(phone 관리자에 대한 학습의 끝입니다)에 관한 것입니다. 다루어야 합니다. 대부분의 개발 요구 사항이 충족되었습니다. 부족한 점이 있으면 언제든지 말씀해 주세요~감사합니다~