版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
廣播接收器BroadcastReceiver廣播分類,注冊廣播接收器,廣播生命周期,發(fā)送廣播Android后臺線程線程,Handler消息傳遞機(jī)制,異步任務(wù)AsyncTask等消息通知NotificationNotification,簡單通知應(yīng)用,自定義通知欄目錄CONTENTS010203服務(wù)ServiceService的生命周期,使用Service04
后臺處理第10章消息通知NotificationPART.01消息通知NotificationNotification類在android.app.Notification包中。它是一種提示簡短、即時消息的通知方式。Notification無須Activity,將消息內(nèi)容以圖標(biāo)的形式顯示在手機(jī)狀態(tài)欄中。按住狀態(tài)欄往下拉,以抽屜式操作方式拉開通知欄。在Android中,Notification包含如下功能:創(chuàng)建新的通知欄圖標(biāo)。在擴(kuò)展的通知欄窗口還可以推送額外的信息(也可以發(fā)起一個Intent),閃爍/LED,讓手機(jī)振動,發(fā)出聲音(鈴聲、媒體庫歌曲)等。Notification類消息通知Notification每個通知都是一個Notification對象,通知的內(nèi)容可以由某個UI信息或某個操作指定。從Android8.0(API26)開始,所有通知都必須分配一個渠道,否則通知將不會顯示。創(chuàng)建通知的方式使用Notification.Builder類Notification.Builder類可以十分方便地創(chuàng)建通知欄中的各個域,并生成各個域中的視圖內(nèi)容。NotificationChannel是通知渠道類,可使用setChannelId(StringchannelId)方法為Notification.Builder對象添加渠道。例如創(chuàng)建一個名為not1的通知對象,渠道號為channelId,代碼片段如下:Notification.Builderbuilder=newNotification.Builder(ctx);builder.setContentIntent(contentIntent).setContent(notify_music).setTicker(song).setSmallIcon(R.drawable.ic_notif_s);if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){//如果在Android8.0以上版本
builder.setChannelId(channelId);}Notificationnot1=builder.build();創(chuàng)建通知消息通知Notification創(chuàng)建通知的方式使用NotificationCompat.Builder類從Android8.0之后,越來越多的開發(fā)者使用AndroidX支持庫中的NotificationCompatAPI來創(chuàng)建通知對象。NotificationCompat類位于androidx.core.app.NotificationCompat包中。創(chuàng)建Notification對象,需要使用其子類NotificationCompat.Builder來創(chuàng)建通知對象并設(shè)置通知內(nèi)容和渠道。NotificationCompat.Builder類的構(gòu)造函數(shù)為:NotificationCompat.Builder(Contextcontext,StringchannelId)其中,參數(shù)context為上下文,參數(shù)channelId為渠道ID。使用NotificationCompat.Builder或Notification.Builder創(chuàng)建Notification對象,二者的用法基本相似,用來設(shè)置通知欄內(nèi)容和顯示視圖的方法也大致相同。創(chuàng)建通知消息通知Notification設(shè)置通知欄內(nèi)容的常用方法方法說明setAutoCancel(booleanautoCancel)設(shè)置該通知是否自動清除。若為true,則點擊該通知后,通知會自動消失;若為false,則相反setContentInfo(CharSequenceinfo)設(shè)置通知欄右下方的文本。若調(diào)用該方法,則setNumber的設(shè)置失效setContentIntent(PendingIntentintent)設(shè)置內(nèi)容的延遲意圖PendingIntent,點擊該通知時觸發(fā)該意圖setContentText(CharSequencetext)設(shè)置通知欄里的內(nèi)容文本setContentTitle(CharSequencetitle)設(shè)置通知欄里的標(biāo)題文本setDeleteIntent(PendingIntentintent)設(shè)置刪除延遲意圖PendingIntent,滑掉該通知時觸發(fā)該動作setLargeIcon(Bitmapb/Iconicon)設(shè)置通知欄里的大圖標(biāo)setNumber(intnumber)設(shè)置通知欄右下方的數(shù)字,可與setProgress聯(lián)合使用,表示當(dāng)前的進(jìn)度數(shù)值setProgress(intmax,intprogress,booleanindeterminate)設(shè)置進(jìn)度條與當(dāng)前進(jìn)度。進(jìn)度條位于標(biāo)題文本與內(nèi)容文本中間setSmallIcon(inticon/Iconicon)設(shè)置狀態(tài)欄里的小圖標(biāo)setSubText(CharSequencetext)設(shè)置通知欄里的附加說明文本,位于內(nèi)容文本下方。若調(diào)用該方法,則setProgress的設(shè)置失效setTicker(CharSequencetickerText)設(shè)置狀態(tài)欄里的提示文本setUsesChronometer(booleanb)設(shè)置是否顯示計數(shù)器。若為true,不顯示推送時間,動態(tài)顯示從通知被推送到當(dāng)前的時間間隔setWhen(longwhen)設(shè)置推送時間,格式為“時:分”。推送時間在通知欄右方顯示setShowWhen(booleanshow)設(shè)置是否顯示推送時間build()構(gòu)建Notification對象。在以上參數(shù)都設(shè)置完畢后,調(diào)用該方法返回Notification對象。消息通知Notification在設(shè)置Notification對象時,至少包含以下內(nèi)容:調(diào)用setSmallIcon()方法,否則在狀態(tài)欄就不會顯示通知消息。調(diào)用setContentTitle()方法,否則在通知欄就不會顯示標(biāo)題。調(diào)用setContentText()方法,否則在通知欄就不會顯示詳細(xì)文本。其它的參數(shù)都是可選項,在應(yīng)用中根據(jù)需求來設(shè)置。例如使用NotificationCompat.Builder來創(chuàng)建一個Notification對象noti,代碼片段如下:Notificationnoti=newNotificationCompat.Builder(mContext,mChannelId).setContentTitle("Mynotification").setContentText("HelloWorld!").setSmallIcon(R.drawable.notification_icon).setLargeIcon(aBitmap).build();消息通知Notification在通知欄中有些設(shè)置方法是互斥的,在同一時間不能同時調(diào)用。setWhen()與setUsesChronometer()同一時間只能調(diào)用一個,因為推送時間與計數(shù)器都位于通知欄的右邊,無法同時顯示。setSubText()與setProgress同一時間只能調(diào)用一個,因為附加說明與進(jìn)度條都位于標(biāo)題文本的下方,無法同時顯示。setNumber()與setContentInfo()同一時間只能調(diào)用一個,因為計數(shù)值與提示都位于通知欄的右下方,無法同時顯示。可以為通知添加一些操作,通知操作允許用戶直接從通知轉(zhuǎn)到應(yīng)用中的Activity。從通知轉(zhuǎn)到Activity,可通過調(diào)用setContentIntent()來添加PendingIntent。一個通知可以提供多個操作。例如,暫停鬧鈴或立即答復(fù)短信等。注意消息通知NotificationNotificationManager類位于android.app.NotificationManager包中,主要負(fù)責(zé)將Notification在狀態(tài)欄顯示出來和取消等管理服務(wù)。在創(chuàng)建NotificationManager類對象時,必須使用getSystemService(String)方法,其參數(shù)是Context.NOTIFICATION_SERVICE用于初始化NotificationManager對象。NotificationManager的常用方法管理通知方法說明cancel(intid)取消指定ID的Notification。如果是一個短暫的Notification,試圖將其隱藏,如果是一個持久的Notification,將從狀態(tài)欄中移走cancelAll()取消以前顯示的一個所有Notificationnotify(intid,Notificationnotification)把Notification持久地推送到狀態(tài)欄上,id是指該Notification的ID號消息通知Notification在Android8.0及更高版本上使用通知,首先必須向系統(tǒng)中注冊應(yīng)用的通知渠道,傳遞通知渠道所需要的信息。創(chuàng)建NotificationChannel實例時,NotificationChannel構(gòu)造函數(shù)需要一個描述重要級別參數(shù)importance。NotificationManager類關(guān)于重要級別的常量管理通知常量名值說明IMPORTANCE_HIGH4開啟通知,發(fā)出提示音,狀態(tài)欄中顯示,會在屏幕上方彈出懸浮彈框IMPORTANCE_DEFAULT3開啟通知,發(fā)出提示音,狀態(tài)欄中顯示,但是不會彈出IMPORTANCE_LOW2開啟通知,狀態(tài)欄中顯示,但是不發(fā)出提示音,不會彈出IMPORTANCE_MIN1開啟通知,但沒有提示音,狀態(tài)欄中無顯示,不會彈出IMPORTANCE_NONE0關(guān)閉通知消息通知Notification在Android8.0(API26)前后,創(chuàng)建通知渠道對象的要求不同。創(chuàng)建通知渠道實例要考慮到應(yīng)用的兼容性,對于不同的Android
SDK版本,創(chuàng)建代碼有所不同。privatevoidcreateNotificationChannel(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){StringchannelId=getString(R.string.channel_id);StringchannelName=getString(R.string.channel_name);intimportance=NotificationManager.IMPORTANCE_DEFAULT;NotificationChannelchannel=newNotificationChannel(channelId,channelName,importance);NotificationManagernotificationManager=getSystemService(NotificationManager.class);notificationManager.createNotificationChannel(channel);}}消息通知Notification創(chuàng)建NotificationManager實例。如果是Android8以上的版本,創(chuàng)建NotificationChannel實例。創(chuàng)建Notification對象。通過NotificationManager實例把通知推送到狀態(tài)欄上。簡單通知開發(fā)基本步驟消息通知Notification設(shè)計思路設(shè)計兩個Activity頁面,第一個頁面設(shè)計一個按鈕,單擊該按鈕跳轉(zhuǎn)到第二個頁面。在第二個頁面中設(shè)計兩個輸入框和一個按鈕,輸入通知的標(biāo)題和內(nèi)容,單擊按鈕發(fā)送簡單通知到狀態(tài)欄,并且在展開通知信息列表中,點擊該條通知信息可跳轉(zhuǎn)回到第一個頁面?!景咐?0.1】輸入通知的標(biāo)題和內(nèi)容,并為通知設(shè)置小圖標(biāo)和大圖標(biāo),通過點擊按鈕發(fā)送到狀態(tài)欄中。開發(fā)步驟準(zhǔn)備顏色資源。編寫res/values目錄下的colors.xml文件,分別聲明black、white、darkgrey和blue等顏色。準(zhǔn)備圖片和背景資源。為通知的小圖和大圖準(zhǔn)備圖片資源;同時編寫文本輸入框的選擇樣式描述文件,編寫輸入框獲取焦點時的圖形背景描述文件和文本輸入框失去焦點時的圖形背景描述文件。設(shè)計布局。在res/layout目錄下有兩個布局文件,activity_main.xml是第一個頁面的布局文件,activity_simplenotify.xml是第二個頁面的布局文件。開發(fā)邏輯代碼。編寫兩個Activity類的實現(xiàn)代碼文件,分別用于實現(xiàn)第一個頁面和第二個頁面的控制。消息通知NotificationNotifySimpleActivity.java代碼片段20@TargetApi(Build.VERSION_CODES.JELLY_BEAN)21publicclassNotifySimpleActivityextendsAppCompatActivityimplementsOnClickListener{25privateNotificationManagermManager;26privateStringchannelId="msg";27privateStringchannelName="消息";30protectedvoidonCreate(BundlesavedInstanceState){31super.onCreate(savedInstanceState);32setContentView(R.layout.activity_simplenotify);33et_title=(EditText)findViewById(R.id.et_title);34et_message=(EditText)findViewById(R.id.et_message);35mManager=(NotificationManager)getSystemService(NOTIFICATION_SERVICE);37if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){38intimportance=NotificationManager.IMPORTANCE_DEFAULT;39createNotificationChannel(channelId,channelName,importance);40}42findViewById(R.id.btn_send_simple).setOnClickListener(this);}46publicvoidonClick(Viewv){47if(v.getId()==R.id.btn_send_simple){48Stringtitle=et_title.getText().toString();49Stringmessage=et_message.getText().toString();50sendSimpleNotify(title,message);51}52}54@RequiresApi(api=Build.VERSION_CODES.O)55privatevoidcreateNotificationChannel(StringchannelId,StringchannelName,intimportance){56NotificationChannelchannel=newNotificationChannel(channelId,channelName,importance);57mManager.createNotificationChannel(channel);58}60privatevoidsendSimpleNotify(Stringtitle,Stringmessage){61IntentclickIntent=newIntent(this,MainActivity.class);62PendingIntentcontentIntent=PendingIntent.getActivity(this,63R.string.app_name,clickIntent,PendingIntent.FLAG_UPDATE_CURRENT);66Notification.Buildernotification_builder=newNotification.Builder(this)67.setContentIntent(contentIntent)68.setContentTitle(title)69.setContentText(message)70.setWhen(System.currentTimeMillis())71.setSmallIcon(R.drawable.ic_smlp)72.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_largp))73.setAutoCancel(true);74if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){75notification_builder.setColor(getResources().getColor(R.color.colorPrimary,null));76notification_builder.setChannelId(channelId);77}78Notificationnotification=notification_builder.build();92mManager.notify(1,notification);93}消息通知Notification運(yùn)行結(jié)果(a)初始運(yùn)行界面(b)輸入通知標(biāo)題(c)單擊發(fā)送按鈕(d)向下拉開通知欄消息通知NotificationsetContent(RemoteViewsviews)方法,其功能是為通知欄設(shè)置一個用戶定制的通知欄視圖,取代系統(tǒng)默認(rèn)的視圖模板。RemoteViews被稱為遠(yuǎn)程視圖。RemoteViews類位于android.widget.RemoteViews包中,它就是一個小型的簡化的頁面,與Activity頁面相比,在功能上有所減少,受限制較多。RemoteViews不支持所有的控件,也不支持自定義控件。支持的布局類型有:FrameLyout、LinearLayout、RelativeLayout、GridLayout;支持的控件有:Button、ImageView、ImageButton、ProgressBar、TextView、ListView、GridView、Chronometer(計時器)、AnalogClock(模擬時鐘)等。注意,不能使用EditText。自定義通知欄消息通知Notification創(chuàng)建RemoteViews對象使用的構(gòu)造方法為:publicRemoteViews(StringpackageName,intlayoutId){this(getApplicationInfo(packageName,UserHandle.myUserId()),layoutId);}其中第一個參數(shù)是應(yīng)用所在包名,第二個參數(shù)是布局文件的id。RemoteViews不能使用findViewById()方法,從而就不能獲取RemoteViews中的子View。它通過一系列的set方法來設(shè)置控件。RemoteViews通過使用PendingIntent,并調(diào)用setOnClickPendingIntent()方法來實現(xiàn)對View的點擊事件。RemoteViews消息通知NotificationRemoteViews中常用的方法方法說明setChronometer(intviewId,longbase,Stringformat,booleanstarted)設(shè)置計時器信息setImageViewBitmap(intviewId,Bitmapbitmap)設(shè)置ImagView或ImageButton控件的位圖對象setImageViewResource(intviewId,intsrcId)設(shè)置ImagView或ImageButton控件的圖像資源IDsetImageViewUri(intviewId,Uriuri)設(shè)置ImagView或ImageButton控件的圖像的URIsetProgressBar(intviewId,intmax,intprogress,booleanindeterminate)設(shè)置進(jìn)度條信息,包括最大值和當(dāng)前進(jìn)度setTextColor(intviewId,intcolor)設(shè)置指定TextView或Button控件的文字顏色setTextViewCompoundDrawables(intviewId,intleft,inttop,intright,intbottom)設(shè)置指定TextView或Button控件的文字周圍圖標(biāo)setTextViewText(intviewId,CharSequencetext)設(shè)置指定TextView或Button控件的文字內(nèi)容setTextViewTextSize(intviewId,intunits,floatsize)設(shè)置指定TextView或Button控件的文字大小setViewPadding(intviewId,intleft,inttop,intright,intbottom)設(shè)置指定控件的間距setViewVisibility(intviewId,intvisibility)設(shè)置指定控件是否可見setOnClickPendingIntent(intviewId,PendingIntentpendingIntent)設(shè)置指定控件的點擊響應(yīng)事件,需要先定義PendingIntent消息通知Notification定義一個布局文件。創(chuàng)建一個RemoteViews對象。調(diào)用一系列set方法實例化RemoteViews對象。通過Notification.setContent()方法加載到通知對象中。自定義通知欄視圖將使用RemoteViews。其基本步驟如下消息通知Notification設(shè)計思路設(shè)計兩個Activity頁面,第一個布局是頁面的界面,設(shè)計兩個按鈕,一個是播放時發(fā)送通知,另一個是暫停時發(fā)送通知。第二個布局是通知欄界面,設(shè)計一個進(jìn)度條,用于呈現(xiàn)發(fā)送時刻音樂播放的進(jìn)度。在本例中使用RemoteViews加載自定義界面到通知對象。點擊通知欄返回主頁面?!景咐?0.2】播放音樂時或暫停音樂時發(fā)送通知,要求定制通知欄視圖,設(shè)置通知欄的信息包括:大圖標(biāo),進(jìn)度、進(jìn)度條、通知內(nèi)容、計時與按鈕。開發(fā)步驟準(zhǔn)備顏色資源。編寫res/values目錄下的colors.xml文件,分別聲明black、white、darkgrey和blue等顏色。準(zhǔn)備圖片和背景資源。為通知的小圖和大圖準(zhǔn)備圖片資源;同時編寫文本輸入框的選擇樣式描述文件,編寫輸入框獲取焦點時的圖形背景描述文件和文本輸入框失去焦點時的圖形背景描述文件。設(shè)計布局。在res/layout目錄下有兩個布局文件,activity_main.xml是第一個頁面的布局文件,notify_remoteview.xml是通知欄的布局文件。開發(fā)邏輯代碼。消息通知Notificationnotify_remoteview.xml代碼片段1<ProgressBar2android:id="@+id/pb_play"3style="?android:attr/progressBarStyleHorizontal"4android:layout_width="match_parent"5android:layout_height="0dp"6android:layout_weight="1"7android:max="100"8android:progress="10"/>1<Chronometer2android:id="@+id/chr_play"3android:layout_width="match_parent"4android:layout_height="0dp"5android:layout_weight="1"/>聲明進(jìn)度條的代碼片段:聲明計時器的代碼片段:消息通知NotificationNotifySimpleActivity.java代碼片段45NotificationManagernotifyMgr=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);46if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){47NotificationChannelchannel=newNotificationChannel(channelId,channName,NotificationManager.IMPORTANCE_HIGH);48notifyMgr.createNotificationChannel(channel);49}50notifyMgr.notify(R.string.app_name,notify);51}53privateNotificationgetNotify(Contextctx,Stringevent,Stringsong,booleanisPlay,intprogress,longtime){54IntentpIntent=newIntent(event);55PendingIntentnIntent=PendingIntent.getBroadcast(ctx,R.string.app_name,pIntent,PendingIntent.FLAG_UPDATE_CURRENT);57RemoteViewsnotify_music=newRemoteViews(ctx.getPackageName(),R.layout.notify_remoteview);58if(isPlay==true){59notify_music.setTextViewText(R.id.btn_play,"暫停");60notify_music.setTextViewText(R.id.tv_progress,"播放進(jìn)度:"+String.valueOf(progress)+"%");61notify_music.setTextViewText(R.id.tv_play,song+"正在播放");62notify_music.setChronometer(R.id.chr_play,time,"%s",true);63}else{64notify_music.setTextViewText(R.id.btn_play,"繼續(xù)");65notify_music.setTextViewText(R.id.tv_progress,"播放進(jìn)度:"+String.valueOf(progress)+"%");66notify_music.setTextColor(R.id.tv_progress,getResources().getColor(R.color.red));67notify_music.setTextViewText(R.id.tv_play,song+"暫停播放");68notify_music.setTextColor(R.id.tv_play,getResources().getColor(R.color.red));69notify_music.setChronometer(R.id.chr_play,time,"%s",false);70}71notify_music.setProgressBar(R.id.pb_play,100,progress,false);72notify_music.setOnClickPendingIntent(R.id.btn_play,nIntent);74Intentintent=newIntent(ctx,MainActivity.class);75PendingIntentcontentIntent=PendingIntent.getActivity(76ctx,R.string.app_name,intent,PendingIntent.FLAG_UPDATE_CURRENT);77 78Notification.Builderbuilder=newNotification.Builder(ctx);79builder.setContentIntent(contentIntent)80.setContent(notify_music)81.setTicker(song)82.setSmallIcon(R.drawable.ic_notif_s);83if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){84builder.setChannelId(channelId);85}86Notificationnotify=builder.build();87returnnotify;88}消息通知Notification運(yùn)行結(jié)果(a)初始運(yùn)行界面(b)正在播放通知信息(c)單擊暫停播放按鈕(d)暫停播放通知信息廣播接收器BroadcastReceiverPART.02廣播的內(nèi)容我們要發(fā)送的廣播內(nèi)容封裝在一個Intent對象中,這個Intent可以攜帶我們要傳送的數(shù)據(jù)。廣播的內(nèi)容可以來自系統(tǒng),也可以來自其他應(yīng)用項目。Android內(nèi)置了很多系統(tǒng)級別的廣播。常用的系統(tǒng)廣播的intent的action常量如下表。常量名action值系統(tǒng)操作ACTION_AIRPLANE_MODE_CHANGEDent.action.AIRPLANE_MODE關(guān)閉或打開飛行模式ACTION_BATTERY_CHANGEDent.action.BATTERY_CHANGED充電時或電量發(fā)生變化ACTION_BATTERY_LOWent.action.BATTERY_LOW電池電量低ACTION_BATTERY_OKAYent.action.BATTERY_OKAY電池電量充足(即從電量低變化到飽滿時會發(fā)出廣播)ACTION_BOOT_COMPLETEDent.action.BOOT_COMPLETED系統(tǒng)啟動完成后(僅廣播一次)ACTION_CAMERA_BUTTONent.action.CAMERA_BUTTON按下照相時的拍照按鍵(硬件按鍵)時ACTION_CLOSE_SYSTEM_DIALOGent.action.CLOSE_SYSTEM_DIALOGS屏幕鎖屏ACTION_DATE_CHANGEDent.action.DATE_CHANGED日期改變ACTION_MEDIA_EJECTent.action.MEDIA_EJECT插入或拔出外部媒體ACTION_PACKAGE_ADDEDent.action.PACKAGE_ADDED成功安裝APKACTION_PACKAGE_REMOVEDent.action.PACKAGE_REMOVED成功刪除APKACTION_REBOOTent.action.REBOOT重啟設(shè)備ACTION_SHUTDOWNent.action.ACTION_SHUTDOWN關(guān)閉系統(tǒng)時廣播的分類普通廣播(Normalbroadcast)
是一種完全異步執(zhí)行的廣播。當(dāng)廣播發(fā)出后,所有廣播接收器幾乎會在同一時刻接收到這條廣播。這類廣播效率比較高,但所有接收器的執(zhí)行順序不確定。缺點是接收者不能將處理結(jié)果傳遞給下一個接收者,并且無法截斷廣播的傳播有序廣播(Orderedbroadcast)是一種按照優(yōu)先級依次執(zhí)行的廣播。數(shù)值越大優(yōu)先級越高,廣播發(fā)出之后同一時刻只有一個廣播接收器能收到這條廣播消息。當(dāng)廣播接收器接收到廣播后,只有這個廣播接收器中的邏輯執(zhí)行完畢后,廣播才繼續(xù)傳遞到下一個廣播接收器,并且可以使用把執(zhí)行結(jié)果傳遞給下一個接收器,或截斷正在傳遞的廣播。本地廣播(LocalBroadcast)是局部廣播,只在進(jìn)程內(nèi)傳播,可避開其他程序的廣播,比系統(tǒng)全局廣播更高效,因此無需擔(dān)心安全漏洞隱患。注冊廣播接收器在AndroidManifest.xml的<application>元素里添加<receiver>元素,并設(shè)置要接收的action。使用清單文件聲明廣播接收器,系統(tǒng)軟件包管理器會在應(yīng)用安裝時注冊接收器。當(dāng)系統(tǒng)收到廣播消息會發(fā)送廣播到Android應(yīng)用上,如果該應(yīng)用還沒有啟動,系統(tǒng)也可以啟動該應(yīng)用并發(fā)送廣播。注意,在Android8.0(API26)版本以后,限制了大多數(shù)系統(tǒng)級別的隱式廣播在清單文件中聲明,只有少數(shù)的常用的隱式廣播可以在清單文件中聲明。如果是注冊有序廣播,則需要添加priority屬性,設(shè)置優(yōu)先級別,其范圍從-1000到1000之間。例如:<receiverandroid:name=".BatteryChangedReceiver"android:exported="true"><intent-filterandroid:priority="1000"><actionandroid:name="ent.action.BATTERY_CHANGED"/><categoryandroid:name="ent.category.DEFAULT"/></intent-filter></receiver>靜態(tài)注冊注冊廣播接收器在邏輯代碼文件中,有相應(yīng)的廣播接收器子類實現(xiàn),代碼片斷如下:publicclassBatteryChangedReceiverextendsBroadcastReceiver{privatestaticfinalStringTAG="BatteryChangedReceiver";@OverridepublicvoidonReceive(Contextcontext,Intentintent){//在這里定義事件響應(yīng)處理
intcurrLevel=intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0);//當(dāng)前電量
inttotal=intent.getIntExtra(BatteryManager.EXTRA_SCALE,1);//總電量
intpercent=currLevel*100/total;StringBuildersb=newStringBuilder();sb.append("battery:"+percent+"%");//生成當(dāng)前電量百分比字符串
Stringlog=sb.toString();Log.d(TAG,log);Toast.makeText(context,log,Toast.LENGTH_LONG).show();}}靜態(tài)注冊注冊廣播接收器在應(yīng)用首次啟動的時候,系統(tǒng)會自動實例化靜態(tài)注冊的BroadcastReceiver,然后將這個BroadcastReceiver注冊到系統(tǒng)中。無論該應(yīng)用項目是否處于活動狀態(tài),BroadcastReceiver始終處于被監(jiān)聽狀態(tài)。通過這種方式注冊的廣播,即使應(yīng)用被銷毀,依然能收到廣播。靜態(tài)注冊的廣播,耗電、占內(nèi)存、不受程序生命周期影響,所以在Android8.0以后禁止了大部分廣播的靜態(tài)注冊。本地廣播也無法使用靜態(tài)注冊方式。靜態(tài)注冊的特點注冊廣播接收器動態(tài)注冊是在類的實現(xiàn)代碼中,使用上下文來注冊廣播接收器。實現(xiàn)的步驟:創(chuàng)建BroadcastReceiver的對象。創(chuàng)建IntentFilter并調(diào)用registerReceiver(BroadcastReceiver,IntentFilter)來注冊接收器。代碼片斷如下:BroadcastReceiverbr=newMyBroadcastReceiver();IntentFilterfilter=newIntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);//添加Intent的actionthis.registerReceiver(br,filter);registerReceiver()方法,第一個參數(shù)是指定接收器對象,第二個參數(shù)是IntentFilter對象。注意,IntentFilter對象內(nèi)要設(shè)置接收的action屬性。動態(tài)注冊的廣播接收器,只要在該上下文有效時,注冊的接收器就會接收廣播。動態(tài)注冊廣播接收器的生命周期當(dāng)系統(tǒng)監(jiān)聽到有廣播消息發(fā)出時開始,創(chuàng)建新的BroadcastReceiver對象,然后該對象調(diào)用onReceive(Context,Intent)方法,在此期間BroadcastReceiver對象有效。靜態(tài)注冊接收器:一旦從onReceiver()方法返回代碼,BroadcastReceiver的生命周期結(jié)束。動態(tài)注冊接收器:如果在Activity的上下文onCreate(Bundle)中注冊接收器,則應(yīng)在onDestroy()中注銷。如果在onResume()中注冊接收器,則應(yīng)在onPause()中注銷。注意,BroadcastReceiver的生命周期很短暫,onReceiver()方法的執(zhí)行大約在10秒之內(nèi)。正因為BroadCastReceiver的生命周期很短暫,所以不要在onReceiver()方法中執(zhí)行耗時的操作。BroadcastReceiver生命周期發(fā)送廣播
BroadcastReceiver注冊完之后,這個BroadcastReceiver就能夠接收響應(yīng)的廣播了。在開發(fā)中通過Context類下的方法發(fā)送廣播。對于不同類別的廣播,發(fā)送廣播的方法也不同的。sendBroadcast()方法使用context.sendBroadcast()方法發(fā)送的廣播是普通廣播,所有接收器的執(zhí)行順序不確定。傳遞效率比較高,但不能將處理的結(jié)果傳遞給下一個接收器,且無法終止廣播的傳播。方法格式如下:sendBroadcast(Intentintent)其中參數(shù)intent,是發(fā)送廣播的意圖對象。發(fā)送廣播的方法發(fā)送廣播sendOrderedBroadcast()方法使用context.sendOrderedBroadcast()方法發(fā)送的廣播是有序廣播,發(fā)送有序廣播類似于上級下發(fā)文件,是一級一級地往下發(fā),如果中間級接收失敗,發(fā)送就會終止。所有的廣播接收器都有一個優(yōu)先級參數(shù),范圍在-1000到1000,通過receiver的intent-filter中的android:priority屬性來設(shè)置,數(shù)值越大優(yōu)先級越高。當(dāng)廣播接收器接收到廣播后,可以使用setResult()方法把結(jié)果傳遞給下一個接收者,通過getResult()方法獲取上一個接收者傳遞過來的結(jié)果;也可以通過abortBroadcast()方法丟棄該廣播,截斷該廣播傳遞下去。發(fā)送廣播的方法發(fā)送廣播sendOrderedBroadcast()方法方法格式如下:sendOrderedBroadcast(Intentintent,StringreceiverPermission,BroadcastReceiverresultReceiver,Handlerscheduler,intinitialCode,StringinitialData,BundleinitialExtras)方法中有七個參數(shù):intent,是一個Intent,是發(fā)送廣播的意圖對象,可以攜帶廣播信息;receiverPermission,是一個字符串,用于指定接收權(quán)限,如果為空,則不需要權(quán)限;resultReceiver,是一個廣播接收器,用于指出有序廣播的最終廣播接收者,該最終接收器可以不在清單文件中配置,仍會接收到廣播;scheduler,是一個線程,若傳null,則默認(rèn)是在主線程中;initialCode,是一個整數(shù),用于初始化的一個值。默認(rèn)值為Activity.RESULT_OK;initialData,是一個字符串,用于發(fā)送廣播的初始化數(shù)據(jù)(相當(dāng)于一條廣播數(shù)據(jù)),可為null;initialExtras,是一個Bundle,用于綁定數(shù)據(jù)傳遞(例如Intent對象extras數(shù)據(jù)),通常為null。發(fā)送廣播的方法發(fā)送廣播LocalBroadcastManager.sendBroadcast()方法LocalBroadcastManager.sendBroadcast()方法會將廣播發(fā)送給與發(fā)送器位于同一應(yīng)用中的接收器,即本地廣播。在Android4.0之后,將本地廣播封裝到LocalBroadcastManager類中。在使用方式上,本地廣播與全局廣播幾乎相同,只是注冊、發(fā)送、注冊廣播接收器時將主調(diào)context實例變成了localBroadcastManager實例。注意,從Android8.0版本開始,對于靜態(tài)注冊的自定義廣播,在調(diào)用sendBroadcast()或sendOrderedBroadcast()方法之前,一定要先指定intent參數(shù)的所在包名,否則廣播無法發(fā)送給接收器。動態(tài)注冊的廣播接收器不需要調(diào)用此方法。發(fā)送廣播的方法發(fā)送廣播設(shè)計思路本例自定義三個BroadcastReceiver,其中第一個接收器使用靜態(tài)方式注冊,接收信息后分別向狀態(tài)欄和Toast提示消息區(qū)發(fā)送廣播;第二個接收器使用動態(tài)方式注冊,只向Toast提示消息區(qū)發(fā)送廣播,并向下一個接收器傳遞信息;第三個接收器是在發(fā)送有序廣播時作為最終接收者。本例應(yīng)用需要定義4個類實現(xiàn)代碼,一個類是Activity,在該類中定義用戶界面的交互、用于動態(tài)注冊和注銷廣播接收器,在按鈕的onClick()方法中使用sendBroadcast()、sendOrderedBroadcast()方法發(fā)送廣播。另外3個類是BroadcastReceiver的子類,在子類中重寫onReceive()方法,用于定義接收器接收到廣播Intent傳遞的信息之后的各種操作?!景咐?0.3】通過兩個按鈕,一個按鈕發(fā)出一個無序廣播,另一個按鈕發(fā)出有序廣播。要求分別將廣播信息發(fā)送到狀態(tài)欄和頁面的Toast提示消息中;并且有序廣播接收器要傳遞信息到下一個接收器。開發(fā)步驟準(zhǔn)備圖片資源。將用于通知的圖標(biāo)的圖片資源復(fù)制到本項目的res/drawable目錄中。設(shè)計布局。在res/layout目錄下編寫activity_main.xml布局文件。開發(fā)邏輯代碼。靜態(tài)注冊設(shè)置。在AndroidManifest.xml中注冊第一個廣播接收器。發(fā)送廣播在AndroidManifest.xml中注冊第一個廣播接收器代碼片段1<receiverandroid:name=".MyBcReceiver1">2<intent-filterandroid:priority="100">3<actionandroid:name="myaction"/>4</intent-filter>5</receiver>發(fā)送廣播MainActivity.java代碼片段16protectedvoidonCreate(BundlesavedInstanceState){17super.onCreate(savedInstanceState);18setContentView(R.layout.activity_main);20sendintent=newIntent();21sendintent.setAction("myaction");22sendintent.putExtra("msg","廣播消息:教育部下發(fā)2020新規(guī)定。");23sendintent.setPackage(getPackageName());//接收器所在包名}30protectedvoidonResume(){31super.onResume();32myReceiver2=newMyBcReceiver2();33myIntentfilter=newIntentFilter("ent.action.MyBcReceiver2");34myIntentfilter.addAction("myaction");35myIntentfilter.setPriority(99);36registerReceiver(myReceiver2,myIntentfilter);37}40protectedvoidonPause(){41super.onPause();42if(myReceiver2!=null){//注銷接收器43unregisterReceiver(myReceiver2);44};45if(myReceiver3!=null){//注銷接收器46unregisterReceiver(myReceiver3);47};48}50privateclassBtnOnClickimplementsView.OnClickListener{51@Override52publicvoidonClick(Viewv){53 54switch(v.getId()){55caseR.id.btn_send:{56//發(fā)送無序廣播57sendBroadcast(sendintent);58break;59}60caseR.id.btn_orderedsend:{61myReceiver3=newMyBcReceiver3();62//發(fā)送有序廣播63sendOrderedBroadcast(sendintent,null,myReceiver3,64null,MainActivity.this.RESULT_OK,null,null);65break;66}67}68}69}發(fā)送廣播MyBcReceiver1.java代碼片段18publicclassMyBcReceiver1extendsBroadcastReceiver{19 20privateNotificationManagermManager;21 22@Override23publicvoidonReceive(Contextcontext,Intentintent){24 25mManager=(NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);26 27if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){28StringchannelId="brd";29StringchannelName="廣播";30intimportance=NotificationManager.IMPORTANCE_DEFAULT;31NotificationChannelchannel=newNotificationChannel(channelId,channelName,importance);32mManager.createNotificationChannel(channel);33}34 35Stringtitle="第1個接收器,接收到廣播消息。";36Stringmessage=intent.getStringExtra("msg");38Notificationnotification=newNotificationCompat.Builder(context,"brd")39.setContentTitle(title)40.setContentText(message)41.setWhen(System.currentTimeMillis())42.setColor(ContextCompat.getColor(context,R.color.colorPrimary))43.setSmallIcon(R.drawable.bc1)44.setAutoCancel(true)45.build();46mManager.notify(1,notification);47 48Toasttt1=Toast.makeText(context,49"這是第1個接收器\n"+intent.getStringExtra("msg"),50Toast.LENGTH_LONG);51tt1.setGravity(Gravity.TOP,0,650);52tt1.show();53Log.e(TAG,"onReceive:"+"第1個廣播接收器");54 55}56}發(fā)送廣播MyBcReceiver2.java代碼片段1publicclassMyBcReceiver2extendsBroadcastReceiver{2 3@Override4publicvoidonReceive(Contextcontext,Intentintent){5Toasttt2=Toast.makeText(context,6"這是第2個接收器\n"+intent.getStringExtra("msg")+"\n并傳遞消息",7Toast.LENGTH_LONG);8tt2.setGravity(Gravity.CENTER,0,200);9tt2.show();10 11Log.e(TAG,"onReceive:"+"第2個廣播接收器,并傳遞消息");12 13Bundlebundle=newBundle();14bundle.putString("first","第2個接收器傳遞的消息啦?。?!");15setResultExtras(bundle);16}17 18}1publicclassMyBcReceiver3extendsBroadcastReceiver{2 3@Override4publicvoidonReceive(Contextcontext,Intentintent){5 6Stringmessage=intent.getExtras().getString("msg");7Bundlebundle=getResultExtras(true);8Stringfirst=bundle.getString("first");9 10Toasttt3=Toast.makeText(context,11"這是第3個接收器\n"+message+"\n\n"12+"同時接收到第2個接收器傳來的消息:"+first,Toast.LENGTH_LONG);13tt3.setGravity(Gravity.BOTTOM,0,120);14tt3.show();15 16Stringss="onReceive:"+"第3個廣播接收器,并接收第2個接收器傳出的消息"+first;17Log.e(TAG,ss);18 19}20 21}MyBcReceiver3.java代碼片段發(fā)送廣播運(yùn)行結(jié)果(a)發(fā)送無序廣播(b)向下拉開通知欄(c)發(fā)送有序廣播由于在API30以上的模擬器中,Toast的setGravity()方法失效,本例在API29模擬器中運(yùn)行。Android后臺線程PART.03Android后臺線程線程是比進(jìn)程更小的執(zhí)行單位。開發(fā)Android應(yīng)用時必須遵守單線程(Single-threaded)模型的原則。當(dāng)一個程序第一次啟動時,Android會啟動一個LINUX進(jìn)程和一個主線程(MainThread)。主線程主要負(fù)責(zé)處理與UI相關(guān)的事件,常被稱為UI線程。UI線程能根據(jù)用戶的要求做出快速響應(yīng),不宜占用太長的時間。如果占用時間超過10秒,Android系統(tǒng)就會給用戶顯示ANR提示信息。Android系統(tǒng)將所有運(yùn)行慢的、耗時操作交給子線程,以解放UI線程,避免阻塞。線程Thread線程Thread所有非主線程就是子線程,子線程一般都是后臺線程,它是由用戶在程序中定義的。Thread類位于java.lang.Thread包中。Thread類常用的方法。方法說明run()包含線程運(yùn)行時所執(zhí)行的代碼start()用于啟動線程sleep(longmillis)線程休眠,以毫秒為單位。線程休眠時交出CPU,讓CPU去執(zhí)行其他的任務(wù),然后線程進(jìn)入阻塞狀態(tài),sleep方法不會釋放鎖yield()使當(dāng)前線程交出CPU,讓CPU去執(zhí)行其他的任務(wù),但不會是線程進(jìn)入阻塞狀態(tài),而是重置為就緒狀態(tài),yield方法不會釋放鎖currentThread()獲取當(dāng)前線程。是靜態(tài)方法,返回值為當(dāng)前線程interrupt()中斷線程。注
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 管道閥門檢測維護(hù)方案
- 交付物品質(zhì)量協(xié)議
- 能源供應(yīng)鏈協(xié)議
- 2025年西安交通大學(xué)第一附屬醫(yī)院醫(yī)學(xué)影像科招聘筆試考試備考試題及答案解析
- 2025年福建醫(yī)科大學(xué)附屬第二醫(yī)院招聘非在編工作人員9人考試筆試模擬試題及答案解析
- 數(shù)據(jù)統(tǒng)計分析技術(shù)合作協(xié)議
- 貨物在途安全跟蹤服務(wù)協(xié)議
- 2025湖南懷化市鶴中一體化發(fā)展事務(wù)中心公開選調(diào)工作人員筆試考試參考題庫及答案解析
- 文化傳媒公司合作協(xié)議
- 2025廣西南寧市興寧區(qū)虹橋路幼兒園招聘1人筆試考試參考試題及答案解析
- 爆破安全規(guī)程解讀課件
- 2025年重慶歷史高考試題及答案
- 網(wǎng)絡(luò)系統(tǒng)管理與維護(hù)期末考試練習(xí)題含答案
- 2025國家開放大學(xué)《公共政策概論》期末機(jī)考題庫及答案
- (2025年標(biāo)準(zhǔn))贍養(yǎng)老人協(xié)議分?jǐn)倕f(xié)議書
- 交強(qiáng)險基本知識培訓(xùn)
- 穿越機(jī)入門教學(xué)課件
- 《二次根式的混合運(yùn)算》教學(xué)設(shè)計
- 地質(zhì)災(zāi)害危險性評估方案報告
- 感術(shù)行動培訓(xùn)課件
- DB44∕T 2552-2024 藥物臨床試驗倫理審查規(guī)范
評論
0/150
提交評論