Android 廣播&服務

BroadCastReceiver

  • 廣播接收者,Android四大組件之一
  • 用於接收廣播Intent的,廣播Intent的發送是經過調用sendBroadCast/sendOrderBroadCast來實現的,一般一個廣播Intent能夠被訂閱了此Intent的多個廣播接收者所接收。

廣播

  • Android中系統經過廣播發布信息,只須要註冊廣播接受者
  • Android系統運行過程當中可能產生不少事件,當這些事件發生時,系統但願通知到其餘應用知道這個事件,因此會發出廣播。
  • 如:開機、電量改變、收發短信、撥打電話、屏幕開關。

定義廣播接收者

  • 必須在清單文件中配置
  • 經過<intent-filter>設置接收什麼廣播
  • 廣播中包含一個intent,當廣播發出時,系統會遍歷
  • 若是廣播接收者被用戶手動中止,那麼不再會啓動了。知道用戶下一次手動啓動該進程,廣播接收者纔會生效。

廣播分類

無序廣播:

  • 全部與廣播中的Intent匹配的廣播接收者都能收到這條廣播,而且接收順序不分前後
  • 無序廣播不能夠被攔截,若是攔截的話會報錯
  • 無序廣播使用sendBroadcast方法來發送

有序廣播:

  • 全部與廣播中的Intent匹配的廣播接收者都能收到這條廣播,可是要按照廣播接收者的優先級
  • 有序廣播能夠被攔截,且優先級高的接收者能夠攔截優先級低的
  • 廣播接收者的優先級取值範圍-1000(最低)~1000(最高)
  • 相同優先級下,接收的順序要看在清單文件中聲明的順序,先聲明的接收者比後聲明的要先接收到廣播。
  • 無序廣播使用sendOrderedBroadcast方法來發送,使用abortBroadcast方法攔截
  • 廣播接收者的優先級在清單文件中聲明接收者時,在<intent-filter>標籤下經過設置"android:property"屬性來設置。

註冊一個廣播接收者有兩種方式

靜態註冊

  • 在清單文件中添加以下配置java

    <!-- 配置廣播接收者 -->
    <receiver android:name="com.istarry.ipbohao.IpCallReceiver" >
        <intent-filter>
    
            <!-- 指定接收那個廣播 -->
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            <!-- <data android:scheme=" " /> -->
        </intent-filter>
    </receiver>

動態註冊:在java代碼中註冊

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter("android.intent.action.MEDIA_UNMOUNTED");
        intentFilter.addDataScheme("file");
        registerReceiver(new IpCallReceiver(), intentFilter);
    }
}

注意:

  • java代碼註冊的廣播接收者優先級要比清單文件的要高,可是當前的廣播接收者的聲明週期的期限和Activity是相關聯的,Activity銷燬,廣播接收者也就再也不起做用。
  • 經過清單文件註冊的廣播接收者在系統中運行一次後就會被註冊到系統中,之後無需運行此廣播接收者,可是也能夠收的到廣播。
  • 接收廣播時要注意在清單文件中添加對應的權限。

IP撥號器

  • 需求:android

    • 監聽用戶撥打電話,在用戶撥打電話號碼前加上17951
  • 1.攔截廣播安全

    <!-- 指定接收(攔截)那個廣播 -->
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
  • 2.須要的權限app

    <uses-permission android:name="android.permission.PROCESSOUTGOINGCALLS" />ide

  • 3.建立一個類IpCallReceiver繼承BroadCastReceiver編碼

    public class IpCallReceiver extends BroadcastReceiver {
        //當收到廣播時,此方法調用
        @Override
        public void onReceive(Context arg0, Intent arg1) {
            //添加17951線路
            //1.拿到用戶撥打的號碼
            //廣播會發送一個Intent,攜帶數據
            String number = getResultData();
            //在號碼前加上17951,並返回數據
            setResultData("17951"+number);
        }
    }
  • 4.在清單文件中註冊廣播接收者線程

    <application
        …… >
        …………
        <!-- 配置廣播接收者 -->
            <receiver android:name="com.istarry.ipbohao.IpCallReceiver" >
             <!-- android:priority="1000"表明着給當前接收者設置優先級,優先級越高就越先接收到廣播,取值-1000~1000 -->
                <intent-filter android:priority="1000">
    
                <!-- 指定接收那個廣播 -->
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
                <!-- <data android:scheme=" " /> -->
              </intent-filter>
            </receiver>
        …………

 


Service

  • Service在Android中是一種長生命週期的組件,它不識閒任何用戶界面,是一個沒有界面的Activity。
  • Service長期在後臺運行,執行不關乎界面的一些操做。好比:網易新聞服務,每隔一分鐘去服務查看是否有最新新聞。
  • Service和Thread有點類似,可是使用Thread不安全,不嚴謹。
  • Service和其餘組件同樣,都是運行在主線程中,所以不能用它來作好事的操做

Android中的進程

Android中的進程種類

進程優先級由高到低,依次爲:code

  • 1. Foreground process 前臺進程(擁有一個正在用戶交互的Activity進程,即onResume()方法被調用)
  • 2. Visible process 可視進程,能夠看見,可是不能夠交互。(擁有一個不在前臺可是依然可見的Activity,即onPause()方法被調用)
  • 3. Service process 服務進程(正在運行一個經過starService()方法啓動的服務進程)
  • 4. Background process 後臺進程(進Activity的onStop方法被調用)
  • 5. Empty process 空進程(當程序退出時,進程沒有被銷燬,而是變成了空進程)。即沒有任何組件活動的進程(進程中沒有服務也沒有Activity)

進程的回收機制

Androidorm

電話錄音機

電話狀態

TelephonyManager,設置PhoneStateListener監聽狀態繼承

  • 空閒
  • 響鈴
  • 摘機狀態(接聽)

權限

<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" />

配置清單文件

<service android:name="com.istarry.luyinji.LuyinjiService" />

建立一個類LuyinjiService繼承Service

public class LuyinjiService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        // 獲取電話管理器
        TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        // 設置偵聽
        // 參數2:設置監聽器只監聽什麼數據
        tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);
    }
    private MediaRecorder recorder;
    class MyListener extends PhoneStateListener {
        // 電話狀態改變時調用此方法
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            // TODO Auto-generated method stub
            super.onCallStateChanged(state, incomingNumber);
            switch (state) {
            case TelephonyManager.CALL_STATE_IDLE:
                System.out.println("空閒");
if (recorder != null) {
                    // 中止錄音
                    recorder.stop();
                    // 釋放佔用的資源
                    recorder.release();
                    recorder = null;
                }
                break;
            case TelephonyManager.CALL_STATE_RINGING:
                System.out.println("響鈴");
                if (recorder == null) {
                    recorder = new MediaRecorder();
                    // 設置錄音源
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    // 設置錄音格式3gp格式
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                    // 設置錄音文件保存位置
                    recorder.setOutputFile("sdcard/voice.3gp");
                    // 設置音頻編碼(一種格式可能有多重種編碼方式)
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    try {
                        // 準備完畢,隨時能夠錄音
                        recorder.prepare();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                System.out.println("摘機");

                if (recorder != null) {
                    recorder.start();
                }
                break;
            }
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        return super.onStartCommand(intent, flags, startId);
    }
}
相關文章
相關標籤/搜索