編輯:關於Android編程
一、問題描述
使用BordercastReceiver和Service組件實現下述功能:
1.當手機處於來電狀態,啟動監聽服務,對來電進行監聽錄音。
2.設置電話黑名單,當來電是黑名單電話,則直接掛斷。
當撥打電話或電話狀態發生改變時,系統就會發出有序廣播,因此我們可以使用BordercastReceiver接受廣播,因BordercastReceiver執行時間短不能執行耗時任務也不能使用子線程,因此我們應啟動一個Service來監聽電話並進行處理
二、加入AIDL文件
Android沒有對外公開結束通話的API,要結束通話就必須使用AIDL與電話管理服務進行通信,並調用服務中的API實現結束通話,這樣需要android 源碼文件NeighboringCellInfo.aidl和ITelephony.aidl添加到項目中,如圖所示:

Android Studio 會自動編譯產生對應的類文件
三、編寫TelReceiver組件
public class TelReceiver extends BroadcastReceiver {
public TelReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Intent i=new Intent(context,ListenPhoneService.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setAction(intent.getAction());
i.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER,
intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER));//電話號碼
i.putExtra(TelephonyManager.EXTRA_STATE,
intent.getStringExtra(TelephonyManager.EXTRA_STATE));//電話狀態
context.startService(i);//啟動服務
}
}
注冊廣播:
<receiver android:name=".TelReceiver" > <intent-filter android:priority="1000" > <action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver>
四、編寫ListenPhoneService組件
public class ListenPhoneService extends Service {
private AudioManager mAudioManager;
private TelephonyManager tm;
public ListenPhoneService() {
}
@Override
public void onCreate() {
super.onCreate();
mAudioManager=(AudioManager)getSystemService(Context.AUDIO_SERVICE);
tm=(TelephonyManager)getSystemService(Service.TELEPHONY_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){//去電廣播,android沒有來電話廣播
}else{//去掉撥打電話就是來電狀態了
//方法1
//獲得來電電話
// String number=intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
//獲得電話狀態
// String state=intent.getStringExtra(TelephonyManager.EXTRA_STATE);
// Log.d("jereh", "incoming phone:" + number);
// Log.d("jereh","call state:"+state);
// TelephonyManager.EXTRA_STATE_IDLE: 沒有來電 或者 掛斷
// TelephonyManagerEXTRA_STATE_OFFHOOK: 接起電話
// TelephonyManager.EXTRA_STATE_RINGING:當電話呼入時,響鈴時
// if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)){
// if(number.equals("13280998858")){//攔截指定的電話號碼
// mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
// Log.d("jereh","電話被攔截");
// stopCall();
// mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);//恢復鈴聲
// }
// }else if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
//接起電話
// recordCall();//開始錄音
// }else if(state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
// stopCall();//停止錄音
// }
//方法2
// 設置一個監聽器,監聽電話狀態
tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE);
}
return super.onStartCommand(intent, flags, startId);
}
/**
* 掛斷電話
*/
private void stopCall(){
try {
//Android的設計將ServiceManager隱藏了,所以只能使用反射機制獲得。
Method method=Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
IBinder binder=(IBinder)method.invoke(null, new Object[]{"phone"});//獲得系統電話服務
ITelephony telephoney=ITelephony.Stub.asInterface(binder);
telephoney.endCall();//掛斷電話
stopSelf();//停止服務
} catch (Exception e) {
e.printStackTrace();
}
}
PhoneStateListener listener=new PhoneStateListener(){
@Override
public void onCallStateChanged(int state,String incomingNumber){
switch (state){
//手機空閒了
case TelephonyManager.CALL_STATE_IDLE:
stopCall();//停止錄音
break;
//接起電話
case TelephonyManager.CALL_STATE_OFFHOOK:
recordCall();//開始錄音
break;
// 響鈴時
case TelephonyManager.CALL_STATE_RINGING:
Log.e("jereh", "來電號碼是:"+ incomingNumber);
// 如果該號碼屬於黑名單
if (incomingNumber.equals("123456")) {
// 如果是黑名單,就進行屏蔽
stopCall();
}
break;
}
}
};
/**
* 停止錄音
*/
private void stopRecord(){
if(recording){
recorder.stop();
recorder.release();
recording=false;
stopSelf();//停止服務
}
}
/**
* 電話錄音
*/
private MediaRecorder recorder;
private boolean recording ;
private void recordCall(){
Log.d("jereh", "record calling")
if( Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
recorder=new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//讀麥克風的聲音
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//設置輸出格式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 編碼方式
File file=new File(Environment.getDownloadCacheDirectory().getAbsolutePath(),"recorder");
if(!file.exists()){
file.mkdir();
}
recorder.setOutputFile(file.getAbsolutePath() + "/"
+ System.currentTimeMillis() + "3gp");// 存放的位置是放在sd卡recorder目錄下
try {
recorder.prepare();
recorder.start();
recording=true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
}
Service XML配置
<service android:name=".ListenPhoneService" android:enabled="true" android:exported="true" > </service>
五、最後別忘了一些權限的設置
<!-- 添加訪問手機電話狀態的權限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 撥打電話權限 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!-- 監聽手機去電的權限 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<!-- 在SDCard中創建與刪除文件權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
好了,以上就是本文的全部所述,希望對大家學習android四大基本組件有所幫助,謝謝。
Android如何實現對系統自帶對話框標題欄進行修改
先上一張圖可以看到,對話框的標題顏色是藍色的,下面還有一根線也是藍色的,在某些情況下,我們想改變程序的主題風格,顏色必須做修改,但又懶得去定制Dialog,
AndroidTestTool開發筆記
前言 這段時間在Testerhome上看了一些有關性能測試的帖子,看別人的東西,始終是別人的,只有自己寫一遍才能體會其中的細節,雖然說不要重復造輪子,但是這種基礎的東西
(Android 基礎(十三)) shape
介紹 簡單來說,shape就是用來在xml文件中定義形狀,代碼解析之後就可以當做Drawable一樣使用官方說明關於shape定義的drawable文件位置:res/dr
Android 開發 之 Fragment 詳解
作者 : 韓曙亮轉載請著名出處 : http://blog.csdn.net/shulianghan/article/details/38064191本博客代碼地址 :