日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android应用开发-广播和服务

發布時間:2025/4/16 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android应用开发-广播和服务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

廣播

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

IP撥號器

原理:接收撥打電話的廣播,修改廣播內攜帶的電話號碼

定義廣播接收者接收打電話廣播

public class CallReceiver extends BroadcastReceiver {//當廣播接收者接收到廣播時,此方法會調用@Overridepublic void onReceive(Context context, Intent intent) {//拿到用戶撥打的號碼String number = getResultData();//修改廣播內的號碼setResultData("17951" + number);} }
  • 在清單文件中定義該廣播接收者接收的廣播類型
<receiver android:name="com.itheima.ipdialer.CallReceiver"><intent-filter ><action android:name="android.intent.action.NEW_OUTGOING_CALL"/></intent-filter></receiver>
  • 接收打電話廣播需要權限
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
  • 即使廣播接收者的進程沒有啟動,當系統發送的廣播可以被該接收者接收時,系統會自動啟動該接收者所在的進程

案例1:IP撥號器

public class CallReceiver extends BroadcastReceiver {//接收到廣播時就會調用@Overridepublic void onReceive(Context context, Intent intent) {//添加IP線路//在打電話廣播中,會攜帶撥打的電話的號碼,通過以下代碼獲取到String number = getResultData();if(number.startsWith("0")){SharedPreferences sp = context.getSharedPreferences("ip", Context.MODE_PRIVATE);String ipNumber = sp.getString("ipNumber", "");//把IP線路號碼添加至用戶撥打號碼的前面number = ipNumber + number;//把新的號碼重新放入廣播中setResultData(number);abortBroadcast();} } } public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){EditText et = (EditText) findViewById(R.id.et);SharedPreferences sp = getSharedPreferences("ip", MODE_PRIVATE);sp.edit().putString("ipNumber", et.getText().toString()).commit();} }

短信攔截器

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

  • 定義廣播接收者接收短信廣播
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
  • 清單文件中配置廣播接收者接收的廣播類型,注意要設置優先級屬性,要保證優先級高于短信應用,才可以實現攔截
<receiver android:name="com.itheima.smslistener.SmsReceiver"><intent-filter android:priority="1000"><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter> </receiver>
  • 添加權限

<uses-permission android:name=”android.permission.RECEIVE_SMS”/>

  • 4.0以后廣播接收者安裝以后必須手動啟動一次,否則不生效
  • 4.0以后廣播接收者如果被手動關閉,就不會再啟動了

案例2:短信防火墻

public class SmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//拿到短信的信息//短信內容封裝在intent中Bundle bundle = intent.getExtras();//以pdus為鍵,取出一個object數組,數組中的每一個元素,都是一條短信Object[] objects = (Object[]) bundle.get("pdus");//拿到廣播中的所有短信for (Object object : objects) {//通過pdu來構造短信SmsMessage sms = SmsMessage.createFromPdu((byte[])object);if(sms.getOriginatingAddress().equals("138438")){//阻止其他廣播接收者收到這條廣播abortBroadcast(); // SmsManager.getDefault().sendTextMessage(sms.getOriginatingAddress(), null, "你是個好人", null, null);} // System.out.println(sms.getMessageBody()); }} }

監聽SD卡狀態

  • 清單文件中定義廣播接收者接收的類型,監聽SD卡常見的三種狀態,所以廣播接收者需要接收三種廣播
<receiver android:name="com.itheima.sdcradlistener.SDCardReceiver"><intent-filter ><action android:name="android.intent.action.MEDIA_MOUNTED"/><action android:name="android.intent.action.MEDIA_UNMOUNTED"/><action android:name="android.intent.action.MEDIA_REMOVED"/><data android:scheme="file"/></intent-filter> </receiver>
  • 廣播接收者的定義
public class SDCardReceiver extends BroadcastReceiver {@Overridepublic 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
  • 清單文件中配置接收開機廣播
<receiver android:name="com.itheima.lesuo.BootReceiver"><intent-filter ><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter> </receiver>
  • 權限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  • 定義廣播接收者
@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);

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

原理:應用在安裝卸載更新時,系統會發送廣播,廣播里會攜帶應用的包名

清單文件定義廣播接收者接收的類型,因為要監聽應用的三個動作,所以需要接收三種廣播

<receiver android:name="com.itheima.app.AppReceiver"><intent-filter ><action android:name="android.intent.action.PACKAGE_ADDED"/><action android:name="android.intent.action.PACKAGE_REPLACED"/><action android:name="android.intent.action.PACKAGE_REMOVED"/><data android:scheme="package"/></intent-filter> </receiver>
  • 廣播接收者的定義
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被重復調用

進程優先級

  • 前臺進程:擁有前臺activity(onResume方法被調用)
  • 可見進程:擁有可見activity(onPause方法被調用)
  • 服務進程:不到萬不得已不會被回收,而且即便被回收,內存充足時也會被重啟
  • 后臺進程:擁有后臺activity(activity的onStop方法被調用了),很容易被回收
  • 空進程:沒有運行任何activity,很容易被回收
  • 電話竊聽器

    • 電話狀態:空閑、響鈴、接聽
    • 獲取電話管理器,設置偵聽
    TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); tm.listen(new MyPhoneStateListener(),PhoneStateListener.LISTEN_CALL_STATE);
    • 偵聽對象的實現
    class MyPhoneStateListener extends PhoneStateListener{//當電話狀態改變時,此方法調用@Overridepublic void onCallStateChanged(int state, String incomingNumber) {// TODO Auto-generated method stubsuper.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 blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}break;}}}

    廣播接收者

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

    創建廣播接收者

    1、 定義java類繼承BroadcastReceiver
    2、 在清單文件中定義receiver節點,定義name屬性,指定廣播接收者java類的全類名
    3、 在intent-filter的節點中,指定action子節點,action的值必須跟要接受的廣播中的action匹配,比如,如果要接受打電話廣播,
    那么action的值必須指定為

    <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
    • 因為打電話廣播中所包含的action,就是”android.intent.action.NEW_OUTGOING_CALL”,所以我們定義廣播接收者時,
      action必須與其匹配,才能收到這條廣播
    • 即便廣播接收者所在進程已經被關閉,當系統發出的廣播中的action跟該廣播接收者的action匹配時,系統會啟動該廣播接收者所在的進程,
      并把廣播發給該廣播接收者

    短信防火墻

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

    廣播的分類

    無序廣播

    • 所有與廣播中的action匹配的廣播接收者都可以收到這條廣播,并且是沒有先后順序,視為同時收到

    有序廣播

    • 所有與廣播中的action匹配的廣播接收者都可以收到這條廣播,但是是有先后順序的,按照廣播接收者的優先級排序

    服務

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

    進程優先級

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

    電話的狀態

    • 空閑狀態
    • 響鈴狀態
    • 摘機狀態

    錄音機

    • 音頻文件的編碼和格式不是一一對應的

    案例3:監聽SD卡狀態

    public class SDStatusReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//判斷收到的到底是什么廣播String action = intent.getAction();if("android.intent.action.MEDIA_MOUNTED".equals(action)){Toast.makeText(context, "SD卡可用", 0).show();}else if("android.intent.action.MEDIA_REMOVED".equals(action)){Toast.makeText(context, "SD卡拔出", 0).show();}else if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){Toast.makeText(context, "SD卡不可用", 0).show();}}}

    案例4:手機勒索軟件

    public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// 啟動Activity,實現開機自動啟動勒索軟件Intent it = new Intent(context, MainActivity.class);//創建任務棧存放啟動的Activityit.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(it);}}

    案例5:監控應用的狀態

    public class APPStatusReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubString action = intent.getAction();Uri uri = intent.getData();if("android.intent.action.PACKAGE_ADDED".equals(action)){Toast.makeText(context, uri.toString() + "被安裝了", 0).show();}if("android.intent.action.PACKAGE_REPLACED".equals(action)){Toast.makeText(context, uri.toString() + "被升級了", 0).show();}if("android.intent.action.PACKAGE_REMOVED".equals(action)){Toast.makeText(context, uri.toString() + "被卸載了", 0).show();}}}

    案例6:發送自定義廣播

    public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){//發送自定義廣播Intent intent = new Intent();//廣播中的action也是自定義的intent.setAction("com.itheima.zdy");sendBroadcast(intent);}}

    案例7:電話錄音機

    public class RecorderService extends Service {private MediaRecorder recorder;@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();//拿到電話管理器TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);//監聽電話狀態//events:決定PhoneStateListener偵聽什么內容tm.listen(new MyListener(), PhoneStateListener.LISTEN_CALL_STATE);}class MyListener extends PhoneStateListener{//一旦電話狀態改變,此方法調用@Overridepublic void onCallStateChanged(int state, String incomingNumber) {// TODO Auto-generated method stubsuper.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);recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);recorder.setOutputFile("sdcard/luyin.3gp");recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);try {recorder.prepare();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}break;case TelephonyManager.CALL_STATE_OFFHOOK:System.out.println("摘機");//開始錄音if(recorder != null){recorder.start();}break;}}}} public class BootReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//啟動錄音機服務Intent it = new Intent(context, RecorderService.class);context.startService(it);}} public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View v){Intent intent = new Intent(this, RecorderService.class);startService(intent);} }

    攔截短信的廣播

    private class InnerSmsReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {System.out.println("InnerSmsReceiver");// 獲取到短信Object[] objects = (Object[]) intent.getExtras().get("pdus");for (Object obj : objects) {SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);// 獲取到短信內容String body = smsMessage.getMessageBody();// 獲取到電話號碼String phone = smsMessage.getDisplayOriginatingAddress();// 根據電話號碼查詢攔截的模式String mode = dao.findNumberMode(phone);/*** 黑名單的攔截模式1 全部攔截(電話攔截+ 短信攔截) 2 電話攔截3 短信攔截*/if ("1".equals(mode) || "3".equals(mode)) {System.out.println("被哥攔截了");//往短信攔截數據庫里面添加數據abortBroadcast();}/*** 根據內容攔截(智能攔截)*/if (body.contains("xue sheng mei")) {System.out.println("學生妹被攔截了");abortBroadcast();}}} }

    注冊靜態廣播

    receiver = new InnerSmsReceiver(); IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); // 設置優先級 filter.setPriority(2147483647); // 注冊一個短信監聽的廣播 registerReceiver(receiver, filter);

    反注冊廣播,防止內存泄露

    public void onDestroy() {super.onDestroy();// 反注冊unregisterReceiver(receiver);receiver = null;// 當不用了。設置為nullmTelephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);listener = null; }

    注冊廣播并設置優先級

    <!-- 攔截黑名單信息--> <receiver android:name="com.itheima.mobilesafe_sh2.receiver.InnerSmsReceiver " ><intent-filter android:priority="1000" ><action android:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter> </receiver>

    總結

    以上是生活随笔為你收集整理的Android应用开发-广播和服务的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。