Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android初級教程理論知識(第六章廣播接受者)

Android初級教程理論知識(第六章廣播接受者)

編輯:關於Android編程

現實中:電台要發布消息,通過廣播把消息廣播出去,使用收音機,就可以收聽廣播,得知這條消息
Android中:系統在運行過程中,會產生很多事件,那麼某些事件產生時,比如:電量改變、收發短信、撥打電話、屏幕解鎖、開機,系統會發送廣播,只要應用程序接收到這條廣播,就知道系統發生了相應的事件,從而執行相應的代碼。使用廣播接收者,就可以收聽廣播

創建廣播接收者

定義java類繼承BroadcastReceiver
在清單文件中定義receiver節點,定義name屬性,指定廣播接收者java類的全類名

在intent-filter的節點中,指定action子節點,action的值必須跟要接受的廣播中的action匹配,比如,如果要接受打電話廣播, 那麼action的值必須指定為
 

<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>

 

因為打電話廣播中所包含的action,就是"android.intent.action.NEWOUTGOINGCALL",所以我們定義廣播接收者時, action必須與其匹配,才能收到這條廣播

即便廣播接收者所在進程已經被關閉,當系統發現系統發出的廣播中的action跟該廣播接收者的action匹配時,系統會啟動該廣播接收者所在的進程, 並把廣播發給該廣播接收者

短信防火牆

系統發送短信廣播時,是怎麼把短信內容存入廣播的,我們就只能怎麼取出來
如果短信過長,那麼發送時會拆分成多條短信發送,那麼短信廣播中就會包含多條短信
4.0之後,廣播接收者所在進程如果從來沒啟動過,那麼廣播接收者不會生效
4.0之後,如果系統自動關閉廣播接收者所在進程,在廣播中的action跟該廣播接收者的action匹配時,系統會啟動該廣播接收者所在的進程,但是如果是用戶手動關閉該進程, 那麼該進程會進入凍結狀態,再也不會啟動了,直到用戶下一次手動啟動該進程

廣播的分類

無序廣播
  • 所有與廣播中的action匹配的廣播接收者都可以收到這條廣播,並且是沒有先後順序,視為同時收到
有序廣播
  • 所有與廣播中的action匹配的廣播接收者都可以收到這條廣播,但是是有先後順序的,按照廣播接收者的優先級排序

服務

Service
運行於後台的一個組件,用來運行適合運行在後台的代碼,服務是沒有前台界面,可以視為沒有界面的activity

進程優先級

前台進程:擁有一個正在與用戶交互的Activity(onResume方法被調用)的進程
可見進程:擁有一個可見但是沒有焦點的Activity(onPause方法被調用)
服務進程:擁有一個通過startService方法啟動的服務
後台進程:擁有一個不可見的Activity(onStop方法被調用)的進程
空進程:沒有擁有任何活動的應用組件的進程

電話錄音機

電話的狀態
空閒狀態
響鈴狀態
摘機狀態
錄音機
音頻文件的編碼和格式不是一一對應的 具體內容:

 

 

廣播

廣播的概念
現實:電台通過發送廣播發布消息,買個收音機,就能收聽
Android:系統在產生某個事件時發送廣播,應用程序使用廣播接收者接收這個廣播,就知道系統產生了什麼事件。 Android系統在運行的過程中,會產生很多事件,比如開機、電量改變、收發短信、撥打電話、屏幕解鎖

使用BroadcastReceiver去接收系統已經定義好的的這些事件。目的是為了方便開發者進行開發。

IP撥號器

原理:接收撥打電話的廣播,修改廣播內攜帶的電話號碼 * 定義廣播接收者接收打電話廣播extends BroadcastReceiver ,相當於買了一個收音機。

public class CallReceiver extends BroadcastReceiver {

    //當廣播接收者接收到廣播時,此方法會調用
    @Override
    public void onReceive(Context context, Intent intent) {
        //拿到用戶撥打的號碼
        String number = getResultData();
        //修改廣播內的號碼
        setResultData("17951" + number);
    }
}

在清單文件中定義該廣播接收者接收的廣播類型,安裝了一塊電池。指定action具體調到一個合適的頻道


    
        
    

接收打電話廣播需要權限


即使廣播接收者的進程沒有啟動,當系統發送的廣播可以被該接收者接收時,系統會自動啟動該接收者所在的進程

短信攔截器

系統收到短信時會產生一條廣播,廣播中包含了短信的號碼和內容

定義廣播接收者接收短信廣播

public void onReceive(Context context, Intent intent) {
//拿到廣播裡攜帶的短信內容
Bundle bundle = intent.getExtras();
Object[] objects = (Object[]) bundle.get("pdus");
for(Object ob : objects ){
    //通過object對象創建一個短信對象
    SmsMessage sms = SmsMessage.createFromPdu((byte[])ob);
    System.out.println(sms.getMessageBody());
    System.out.println(sms.getOriginatingAddress());
}

}

系統創建廣播時,把短信存放到一個數組,然後把數據以pdus為key存入bundle,再把bundle存入intent

清單文件中配置廣播接收者接收的廣播類型,注意要設置優先級屬性,要保證優先級高於短信應用,才可以實現攔截


    
        
    

添加權限


4.0以後廣播接收者安裝以後必須手動啟動一次,否則不生效

4.0以後廣播接收者如果被手動關閉,就不會再啟動了

監聽SD卡狀態

清單文件中定義廣播接收者接收的類型,監聽SD卡常見的三種狀態,所以廣播接收者需要接收三種廣播

 
    
        
        
        
        
    

廣播接收者的定義

public class SDCardReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 區分接收到的是哪個廣播
        String action = intent.getAction();

        if(action.equals("android.intent.action.MEDIA_MOUNTED")){
            System.out.println("sd卡就緒");
        }
        else if(action.equals("android.intent.action.MEDIA_UNMOUNTED")){
            System.out.println("sd卡被移除");
        }
        else if(action.equals("android.intent.action.MEDIA_REMOVED")){
            System.out.println("sd卡被拔出");
        }
    }
}

勒索軟件

接收開機廣播,在廣播接收者中啟動勒索的Activity

清單文件中配置接收開機廣播


    
        
    

權限


定義廣播接收者

@Override
public void onReceive(Context context, Intent intent) {
    //開機的時候就啟動勒索軟件
    Intent it = new Intent(context, MainActivity.class);        
    context.startActivity(it);
}
以上代碼還不能啟動MainActivity,因為廣播接收者的啟動,並不會創建任務棧,那麼沒有任務棧,就無法啟動activity

手動設置創建新任務棧的flag

it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

監聽應用的安裝、卸載、更新

原理:應用在安裝卸載更新時,系統會發送廣播,廣播裡會攜帶應用的包名 * 清單文件定義廣播接收者接收的類型,因為要監聽應用的三個動作,所以需要接收三種廣播

    
        
            
            
            
            
        
    

廣播接收者的定義

public void onReceive(Context context, Intent intent) {
    //區分接收到的是哪種廣播
    String action = intent.getAction();
    //獲取廣播中包含的應用包名
    Uri uri = intent.getData();
    if(action.equals("android.intent.action.PACKAGE_ADDED")){
        System.out.println(uri + "被安裝了");
    }
    else if(action.equals("android.intent.action.PACKAGE_REPLACED")){
        System.out.println(uri + "被更新了");
    }
    else if(action.equals("android.intent.action.PACKAGE_REMOVED")){
        System.out.println(uri + "被卸載了");
    }
}

廣播的兩種類型

無序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播,並且是沒有先後順序(同時收到)
有序廣播:所有跟廣播的intent匹配的廣播接收者都可以收到該廣播,但是會按照廣播接收者的優先級來決定接收的先後順序
  • 優先級的定義:-1000~1000
  • 最終接收者:所有廣播接收者都接收到廣播之後,它才接收,並且一定會接收
  • abortBroadCast:阻止其他接收者接收這條廣播,類似攔截,只有有序廣播可以被攔截

Service

  • 就是默默運行在後台的組件,可以理解為是沒有前台的activity,適合用來運行不需要前台界面的代碼
  • 服務可以被手動關閉,不會重啟,但是如果被自動關閉,內存充足就會重啟
  • startService啟動服務的生命周期
  • onCreate-onStartCommand-onDestroy
  • 重復的調用startService會導致onStartCommand被重復調用

進程優先級

  1. 前台進程:擁有前台activity(onResume方法被調用)
  2. 可見進程:擁有可見activity(onPause方法被調用)
  3. 服務進程:不到萬不得已不會被回收,而且即便被回收,內存充足時也會被重啟
  4. 後台進程:擁有後台activity(activity的onStop方法被調用了),很容易被回收
  5. 空進程:沒有運行任何activity,很容易被回收

電話竊聽器

電話狀態:空閒、響鈴、接聽

獲取電話管理器,設置偵聽

TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);

偵聽對象的實現

class MyPhoneStateListener 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://空閒
            if(recorder != null){
                recorder.stop();
                recorder.release();
            }
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK://摘機
            if(recorder != null){
                recorder.start();
            }
            break;
        case TelephonyManager.CALL_STATE_RINGING://響鈴
            recorder = new MediaRecorder();
            //設置聲音來源
            recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            //設置音頻文件格式
            recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            recorder.setOutputFile("sdcard/haha.3gp");
            //設置音頻文件編碼
            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            try {
                recorder.prepare();
            } catch (IllegalStateException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;
        }
    }
}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved