




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
廣播接收器BroadcastReceiver廣播分類,注冊(cè)廣播接收器,廣播生命周期,發(fā)送廣播Android后臺(tái)線程線程,Handler消息傳遞機(jī)制,異步任務(wù)AsyncTask等消息通知NotificationNotification,簡(jiǎn)單通知應(yīng)用,自定義通知欄目錄CONTENTS010203服務(wù)ServiceService的生命周期,使用Service04
后臺(tái)處理第10章消息通知NotificationPART.01消息通知NotificationNotification類在android.app.Notification包中。它是一種提示簡(jiǎn)短、即時(shí)消息的通知方式。Notification無(wú)須Activity,將消息內(nèi)容以圖標(biāo)的形式顯示在手機(jī)狀態(tài)欄中。按住狀態(tài)欄往下拉,以抽屜式操作方式拉開(kāi)通知欄。在Android中,Notification包含如下功能:創(chuàng)建新的通知欄圖標(biāo)。在擴(kuò)展的通知欄窗口還可以推送額外的信息(也可以發(fā)起一個(gè)Intent),閃爍/LED,讓手機(jī)振動(dòng),發(fā)出聲音(鈴聲、媒體庫(kù)歌曲)等。Notification類消息通知Notification每個(gè)通知都是一個(gè)Notification對(duì)象,通知的內(nèi)容可以由某個(gè)UI信息或某個(gè)操作指定。從Android8.0(API26)開(kāi)始,所有通知都必須分配一個(gè)渠道,否則通知將不會(huì)顯示。創(chuàng)建通知的方式使用Notification.Builder類Notification.Builder類可以十分方便地創(chuàng)建通知欄中的各個(gè)域,并生成各個(gè)域中的視圖內(nèi)容。NotificationChannel是通知渠道類,可使用setChannelId(StringchannelId)方法為Notification.Builder對(duì)象添加渠道。例如創(chuàng)建一個(gè)名為not1的通知對(duì)象,渠道號(hào)為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之后,越來(lái)越多的開(kāi)發(fā)者使用AndroidX支持庫(kù)中的NotificationCompatAPI來(lái)創(chuàng)建通知對(duì)象。NotificationCompat類位于androidx.core.app.NotificationCompat包中。創(chuàng)建Notification對(duì)象,需要使用其子類NotificationCompat.Builder來(lái)創(chuàng)建通知對(duì)象并設(shè)置通知內(nèi)容和渠道。NotificationCompat.Builder類的構(gòu)造函數(shù)為:NotificationCompat.Builder(Contextcontext,StringchannelId)其中,參數(shù)context為上下文,參數(shù)channelId為渠道ID。使用NotificationCompat.Builder或Notification.Builder創(chuàng)建Notification對(duì)象,二者的用法基本相似,用來(lái)設(shè)置通知欄內(nèi)容和顯示視圖的方法也大致相同。創(chuàng)建通知消息通知Notification設(shè)置通知欄內(nèi)容的常用方法方法說(shuō)明setAutoCancel(booleanautoCancel)設(shè)置該通知是否自動(dòng)清除。若為true,則點(diǎn)擊該通知后,通知會(huì)自動(dòng)消失;若為false,則相反setContentInfo(CharSequenceinfo)設(shè)置通知欄右下方的文本。若調(diào)用該方法,則setNumber的設(shè)置失效setContentIntent(PendingIntentintent)設(shè)置內(nèi)容的延遲意圖PendingIntent,點(diǎn)擊該通知時(shí)觸發(fā)該意圖setContentText(CharSequencetext)設(shè)置通知欄里的內(nèi)容文本setContentTitle(CharSequencetitle)設(shè)置通知欄里的標(biāo)題文本setDeleteIntent(PendingIntentintent)設(shè)置刪除延遲意圖PendingIntent,滑掉該通知時(shí)觸發(fā)該動(dòng)作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è)置通知欄里的附加說(shuō)明文本,位于內(nèi)容文本下方。若調(diào)用該方法,則setProgress的設(shè)置失效setTicker(CharSequencetickerText)設(shè)置狀態(tài)欄里的提示文本setUsesChronometer(booleanb)設(shè)置是否顯示計(jì)數(shù)器。若為true,不顯示推送時(shí)間,動(dòng)態(tài)顯示從通知被推送到當(dāng)前的時(shí)間間隔setWhen(longwhen)設(shè)置推送時(shí)間,格式為“時(shí):分”。推送時(shí)間在通知欄右方顯示setShowWhen(booleanshow)設(shè)置是否顯示推送時(shí)間build()構(gòu)建Notification對(duì)象。在以上參數(shù)都設(shè)置完畢后,調(diào)用該方法返回Notification對(duì)象。消息通知Notification在設(shè)置Notification對(duì)象時(shí),至少包含以下內(nèi)容:調(diào)用setSmallIcon()方法,否則在狀態(tài)欄就不會(huì)顯示通知消息。調(diào)用setContentTitle()方法,否則在通知欄就不會(huì)顯示標(biāo)題。調(diào)用setContentText()方法,否則在通知欄就不會(huì)顯示詳細(xì)文本。其它的參數(shù)都是可選項(xiàng),在應(yīng)用中根據(jù)需求來(lái)設(shè)置。例如使用NotificationCompat.Builder來(lái)創(chuàng)建一個(gè)Notification對(duì)象noti,代碼片段如下:Notificationnoti=newNotificationCompat.Builder(mContext,mChannelId).setContentTitle("Mynotification").setContentText("HelloWorld!").setSmallIcon(R.drawable.notification_icon).setLargeIcon(aBitmap).build();消息通知Notification在通知欄中有些設(shè)置方法是互斥的,在同一時(shí)間不能同時(shí)調(diào)用。setWhen()與setUsesChronometer()同一時(shí)間只能調(diào)用一個(gè),因?yàn)橥扑蜁r(shí)間與計(jì)數(shù)器都位于通知欄的右邊,無(wú)法同時(shí)顯示。setSubText()與setProgress同一時(shí)間只能調(diào)用一個(gè),因?yàn)楦郊诱f(shuō)明與進(jìn)度條都位于標(biāo)題文本的下方,無(wú)法同時(shí)顯示。setNumber()與setContentInfo()同一時(shí)間只能調(diào)用一個(gè),因?yàn)橛?jì)數(shù)值與提示都位于通知欄的右下方,無(wú)法同時(shí)顯示??梢詾橥ㄖ砑右恍┎僮鳎ㄖ僮髟试S用戶直接從通知轉(zhuǎn)到應(yīng)用中的Activity。從通知轉(zhuǎn)到Activity,可通過(guò)調(diào)用setContentIntent()來(lái)添加PendingIntent。一個(gè)通知可以提供多個(gè)操作。例如,暫停鬧鈴或立即答復(fù)短信等。注意消息通知NotificationNotificationManager類位于android.app.NotificationManager包中,主要負(fù)責(zé)將Notification在狀態(tài)欄顯示出來(lái)和取消等管理服務(wù)。在創(chuàng)建NotificationManager類對(duì)象時(shí),必須使用getSystemService(String)方法,其參數(shù)是Context.NOTIFICATION_SERVICE用于初始化NotificationManager對(duì)象。NotificationManager的常用方法管理通知方法說(shuō)明cancel(intid)取消指定ID的Notification。如果是一個(gè)短暫的Notification,試圖將其隱藏,如果是一個(gè)持久的Notification,將從狀態(tài)欄中移走cancelAll()取消以前顯示的一個(gè)所有Notificationnotify(intid,Notificationnotification)把Notification持久地推送到狀態(tài)欄上,id是指該Notification的ID號(hào)消息通知Notification在Android8.0及更高版本上使用通知,首先必須向系統(tǒng)中注冊(cè)應(yīng)用的通知渠道,傳遞通知渠道所需要的信息。創(chuàng)建NotificationChannel實(shí)例時(shí),NotificationChannel構(gòu)造函數(shù)需要一個(gè)描述重要級(jí)別參數(shù)importance。NotificationManager類關(guān)于重要級(jí)別的常量管理通知常量名值說(shuō)明IMPORTANCE_HIGH4開(kāi)啟通知,發(fā)出提示音,狀態(tài)欄中顯示,會(huì)在屏幕上方彈出懸浮彈框IMPORTANCE_DEFAULT3開(kāi)啟通知,發(fā)出提示音,狀態(tài)欄中顯示,但是不會(huì)彈出IMPORTANCE_LOW2開(kāi)啟通知,狀態(tài)欄中顯示,但是不發(fā)出提示音,不會(huì)彈出IMPORTANCE_MIN1開(kāi)啟通知,但沒(méi)有提示音,狀態(tài)欄中無(wú)顯示,不會(huì)彈出IMPORTANCE_NONE0關(guān)閉通知消息通知Notification在Android8.0(API26)前后,創(chuàng)建通知渠道對(duì)象的要求不同。創(chuàng)建通知渠道實(shí)例要考慮到應(yīng)用的兼容性,對(duì)于不同的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實(shí)例。如果是Android8以上的版本,創(chuàng)建NotificationChannel實(shí)例。創(chuàng)建Notification對(duì)象。通過(guò)NotificationManager實(shí)例把通知推送到狀態(tài)欄上。簡(jiǎn)單通知開(kāi)發(fā)基本步驟消息通知Notification設(shè)計(jì)思路設(shè)計(jì)兩個(gè)Activity頁(yè)面,第一個(gè)頁(yè)面設(shè)計(jì)一個(gè)按鈕,單擊該按鈕跳轉(zhuǎn)到第二個(gè)頁(yè)面。在第二個(gè)頁(yè)面中設(shè)計(jì)兩個(gè)輸入框和一個(gè)按鈕,輸入通知的標(biāo)題和內(nèi)容,單擊按鈕發(fā)送簡(jiǎn)單通知到狀態(tài)欄,并且在展開(kāi)通知信息列表中,點(diǎn)擊該條通知信息可跳轉(zhuǎn)回到第一個(gè)頁(yè)面?!景咐?0.1】輸入通知的標(biāo)題和內(nèi)容,并為通知設(shè)置小圖標(biāo)和大圖標(biāo),通過(guò)點(diǎn)擊按鈕發(fā)送到狀態(tài)欄中。開(kāi)發(fā)步驟準(zhǔn)備顏色資源。編寫res/values目錄下的colors.xml文件,分別聲明black、white、darkgrey和blue等顏色。準(zhǔn)備圖片和背景資源。為通知的小圖和大圖準(zhǔn)備圖片資源;同時(shí)編寫文本輸入框的選擇樣式描述文件,編寫輸入框獲取焦點(diǎn)時(shí)的圖形背景描述文件和文本輸入框失去焦點(diǎn)時(shí)的圖形背景描述文件。設(shè)計(jì)布局。在res/layout目錄下有兩個(gè)布局文件,activity_main.xml是第一個(gè)頁(yè)面的布局文件,activity_simplenotify.xml是第二個(gè)頁(yè)面的布局文件。開(kāi)發(fā)邏輯代碼。編寫兩個(gè)Activity類的實(shí)現(xiàn)代碼文件,分別用于實(shí)現(xiàn)第一個(gè)頁(yè)面和第二個(gè)頁(yè)面的控制。消息通知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)向下拉開(kāi)通知欄消息通知NotificationsetContent(RemoteViewsviews)方法,其功能是為通知欄設(shè)置一個(gè)用戶定制的通知欄視圖,取代系統(tǒng)默認(rèn)的視圖模板。RemoteViews被稱為遠(yuǎn)程視圖。RemoteViews類位于android.widget.RemoteViews包中,它就是一個(gè)小型的簡(jiǎn)化的頁(yè)面,與Activity頁(yè)面相比,在功能上有所減少,受限制較多。RemoteViews不支持所有的控件,也不支持自定義控件。支持的布局類型有:FrameLyout、LinearLayout、RelativeLayout、GridLayout;支持的控件有:Button、ImageView、ImageButton、ProgressBar、TextView、ListView、GridView、Chronometer(計(jì)時(shí)器)、AnalogClock(模擬時(shí)鐘)等。注意,不能使用EditText。自定義通知欄消息通知Notification創(chuàng)建RemoteViews對(duì)象使用的構(gòu)造方法為:publicRemoteViews(StringpackageName,intlayoutId){this(getApplicationInfo(packageName,UserHandle.myUserId()),layoutId);}其中第一個(gè)參數(shù)是應(yīng)用所在包名,第二個(gè)參數(shù)是布局文件的id。RemoteViews不能使用findViewById()方法,從而就不能獲取RemoteViews中的子View。它通過(guò)一系列的set方法來(lái)設(shè)置控件。RemoteViews通過(guò)使用PendingIntent,并調(diào)用setOnClickPendingIntent()方法來(lái)實(shí)現(xiàn)對(duì)View的點(diǎn)擊事件。RemoteViews消息通知NotificationRemoteViews中常用的方法方法說(shuō)明setChronometer(intviewId,longbase,Stringformat,booleanstarted)設(shè)置計(jì)時(shí)器信息setImageViewBitmap(intviewId,Bitmapbitmap)設(shè)置ImagView或ImageButton控件的位圖對(duì)象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è)置指定控件是否可見(jiàn)setOnClickPendingIntent(intviewId,PendingIntentpendingIntent)設(shè)置指定控件的點(diǎn)擊響應(yīng)事件,需要先定義PendingIntent消息通知Notification定義一個(gè)布局文件。創(chuàng)建一個(gè)RemoteViews對(duì)象。調(diào)用一系列set方法實(shí)例化RemoteViews對(duì)象。通過(guò)Notification.setContent()方法加載到通知對(duì)象中。自定義通知欄視圖將使用RemoteViews。其基本步驟如下消息通知Notification設(shè)計(jì)思路設(shè)計(jì)兩個(gè)Activity頁(yè)面,第一個(gè)布局是頁(yè)面的界面,設(shè)計(jì)兩個(gè)按鈕,一個(gè)是播放時(shí)發(fā)送通知,另一個(gè)是暫停時(shí)發(fā)送通知。第二個(gè)布局是通知欄界面,設(shè)計(jì)一個(gè)進(jìn)度條,用于呈現(xiàn)發(fā)送時(shí)刻音樂(lè)播放的進(jìn)度。在本例中使用RemoteViews加載自定義界面到通知對(duì)象。點(diǎn)擊通知欄返回主頁(yè)面?!景咐?0.2】播放音樂(lè)時(shí)或暫停音樂(lè)時(shí)發(fā)送通知,要求定制通知欄視圖,設(shè)置通知欄的信息包括:大圖標(biāo),進(jìn)度、進(jìn)度條、通知內(nèi)容、計(jì)時(shí)與按鈕。開(kāi)發(fā)步驟準(zhǔn)備顏色資源。編寫res/values目錄下的colors.xml文件,分別聲明black、white、darkgrey和blue等顏色。準(zhǔn)備圖片和背景資源。為通知的小圖和大圖準(zhǔn)備圖片資源;同時(shí)編寫文本輸入框的選擇樣式描述文件,編寫輸入框獲取焦點(diǎn)時(shí)的圖形背景描述文件和文本輸入框失去焦點(diǎn)時(shí)的圖形背景描述文件。設(shè)計(jì)布局。在res/layout目錄下有兩個(gè)布局文件,activity_main.xml是第一個(gè)頁(yè)面的布局文件,notify_remoteview.xml是通知欄的布局文件。開(kāi)發(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)度條的代碼片段:聲明計(jì)時(shí)器的代碼片段:消息通知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)容封裝在一個(gè)Intent對(duì)象中,這個(gè)Intent可以攜帶我們要傳送的數(shù)據(jù)。廣播的內(nèi)容可以來(lái)自系統(tǒng),也可以來(lái)自其他應(yīng)用項(xiàng)目。Android內(nèi)置了很多系統(tǒng)級(jí)別的廣播。常用的系統(tǒng)廣播的intent的action常量如下表。常量名action值系統(tǒng)操作ACTION_AIRPLANE_MODE_CHANGEDent.action.AIRPLANE_MODE關(guān)閉或打開(kāi)飛行模式ACTION_BATTERY_CHANGEDent.action.BATTERY_CHANGED充電時(shí)或電量發(fā)生變化ACTION_BATTERY_LOWent.action.BATTERY_LOW電池電量低ACTION_BATTERY_OKAYent.action.BATTERY_OKAY電池電量充足(即從電量低變化到飽滿時(shí)會(huì)發(fā)出廣播)ACTION_BOOT_COMPLETEDent.action.BOOT_COMPLETED系統(tǒng)啟動(dòng)完成后(僅廣播一次)ACTION_CAMERA_BUTTONent.action.CAMERA_BUTTON按下照相時(shí)的拍照按鍵(硬件按鍵)時(shí)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)時(shí)廣播的分類普通廣播(Normalbroadcast)
是一種完全異步執(zhí)行的廣播。當(dāng)廣播發(fā)出后,所有廣播接收器幾乎會(huì)在同一時(shí)刻接收到這條廣播。這類廣播效率比較高,但所有接收器的執(zhí)行順序不確定。缺點(diǎn)是接收者不能將處理結(jié)果傳遞給下一個(gè)接收者,并且無(wú)法截?cái)鄰V播的傳播有序廣播(Orderedbroadcast)是一種按照優(yōu)先級(jí)依次執(zhí)行的廣播。數(shù)值越大優(yōu)先級(jí)越高,廣播發(fā)出之后同一時(shí)刻只有一個(gè)廣播接收器能收到這條廣播消息。當(dāng)廣播接收器接收到廣播后,只有這個(gè)廣播接收器中的邏輯執(zhí)行完畢后,廣播才繼續(xù)傳遞到下一個(gè)廣播接收器,并且可以使用把執(zhí)行結(jié)果傳遞給下一個(gè)接收器,或截?cái)嗾趥鬟f的廣播。本地廣播(LocalBroadcast)是局部廣播,只在進(jìn)程內(nèi)傳播,可避開(kāi)其他程序的廣播,比系統(tǒng)全局廣播更高效,因此無(wú)需擔(dān)心安全漏洞隱患。注冊(cè)廣播接收器在AndroidManifest.xml的<application>元素里添加<receiver>元素,并設(shè)置要接收的action。使用清單文件聲明廣播接收器,系統(tǒng)軟件包管理器會(huì)在應(yīng)用安裝時(shí)注冊(cè)接收器。當(dāng)系統(tǒng)收到廣播消息會(huì)發(fā)送廣播到Android應(yīng)用上,如果該應(yīng)用還沒(méi)有啟動(dòng),系統(tǒng)也可以啟動(dòng)該應(yīng)用并發(fā)送廣播。注意,在Android8.0(API26)版本以后,限制了大多數(shù)系統(tǒng)級(jí)別的隱式廣播在清單文件中聲明,只有少數(shù)的常用的隱式廣播可以在清單文件中聲明。如果是注冊(cè)有序廣播,則需要添加priority屬性,設(shè)置優(yōu)先級(jí)別,其范圍從-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)注冊(cè)注冊(cè)廣播接收器在邏輯代碼文件中,有相應(yīng)的廣播接收器子類實(shí)現(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)注冊(cè)注冊(cè)廣播接收器在應(yīng)用首次啟動(dòng)的時(shí)候,系統(tǒng)會(huì)自動(dòng)實(shí)例化靜態(tài)注冊(cè)的BroadcastReceiver,然后將這個(gè)BroadcastReceiver注冊(cè)到系統(tǒng)中。無(wú)論該應(yīng)用項(xiàng)目是否處于活動(dòng)狀態(tài),BroadcastReceiver始終處于被監(jiān)聽(tīng)狀態(tài)。通過(guò)這種方式注冊(cè)的廣播,即使應(yīng)用被銷毀,依然能收到廣播。靜態(tài)注冊(cè)的廣播,耗電、占內(nèi)存、不受程序生命周期影響,所以在Android8.0以后禁止了大部分廣播的靜態(tài)注冊(cè)。本地廣播也無(wú)法使用靜態(tài)注冊(cè)方式。靜態(tài)注冊(cè)的特點(diǎn)注冊(cè)廣播接收器動(dòng)態(tài)注冊(cè)是在類的實(shí)現(xiàn)代碼中,使用上下文來(lái)注冊(cè)廣播接收器。實(shí)現(xiàn)的步驟:創(chuàng)建BroadcastReceiver的對(duì)象。創(chuàng)建IntentFilter并調(diào)用registerReceiver(BroadcastReceiver,IntentFilter)來(lái)注冊(cè)接收器。代碼片斷如下:BroadcastReceiverbr=newMyBroadcastReceiver();IntentFilterfilter=newIntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);//添加Intent的actionthis.registerReceiver(br,filter);registerReceiver()方法,第一個(gè)參數(shù)是指定接收器對(duì)象,第二個(gè)參數(shù)是IntentFilter對(duì)象。注意,IntentFilter對(duì)象內(nèi)要設(shè)置接收的action屬性。動(dòng)態(tài)注冊(cè)的廣播接收器,只要在該上下文有效時(shí),注冊(cè)的接收器就會(huì)接收廣播。動(dòng)態(tài)注冊(cè)廣播接收器的生命周期當(dāng)系統(tǒng)監(jiān)聽(tīng)到有廣播消息發(fā)出時(shí)開(kāi)始,創(chuàng)建新的BroadcastReceiver對(duì)象,然后該對(duì)象調(diào)用onReceive(Context,Intent)方法,在此期間BroadcastReceiver對(duì)象有效。靜態(tài)注冊(cè)接收器:一旦從onReceiver()方法返回代碼,BroadcastReceiver的生命周期結(jié)束。動(dòng)態(tài)注冊(cè)接收器:如果在Activity的上下文onCreate(Bundle)中注冊(cè)接收器,則應(yīng)在onDestroy()中注銷。如果在onResume()中注冊(cè)接收器,則應(yīng)在onPause()中注銷。注意,BroadcastReceiver的生命周期很短暫,onReceiver()方法的執(zhí)行大約在10秒之內(nèi)。正因?yàn)锽roadCastReceiver的生命周期很短暫,所以不要在onReceiver()方法中執(zhí)行耗時(shí)的操作。BroadcastReceiver生命周期發(fā)送廣播
BroadcastReceiver注冊(cè)完之后,這個(gè)BroadcastReceiver就能夠接收響應(yīng)的廣播了。在開(kāi)發(fā)中通過(guò)Context類下的方法發(fā)送廣播。對(duì)于不同類別的廣播,發(fā)送廣播的方法也不同的。sendBroadcast()方法使用context.sendBroadcast()方法發(fā)送的廣播是普通廣播,所有接收器的執(zhí)行順序不確定。傳遞效率比較高,但不能將處理的結(jié)果傳遞給下一個(gè)接收器,且無(wú)法終止廣播的傳播。方法格式如下:sendBroadcast(Intentintent)其中參數(shù)intent,是發(fā)送廣播的意圖對(duì)象。發(fā)送廣播的方法發(fā)送廣播sendOrderedBroadcast()方法使用context.sendOrderedBroadcast()方法發(fā)送的廣播是有序廣播,發(fā)送有序廣播類似于上級(jí)下發(fā)文件,是一級(jí)一級(jí)地往下發(fā),如果中間級(jí)接收失敗,發(fā)送就會(huì)終止。所有的廣播接收器都有一個(gè)優(yōu)先級(jí)參數(shù),范圍在-1000到1000,通過(guò)receiver的intent-filter中的android:priority屬性來(lái)設(shè)置,數(shù)值越大優(yōu)先級(jí)越高。當(dāng)廣播接收器接收到廣播后,可以使用setResult()方法把結(jié)果傳遞給下一個(gè)接收者,通過(guò)getResult()方法獲取上一個(gè)接收者傳遞過(guò)來(lái)的結(jié)果;也可以通過(guò)abortBroadcast()方法丟棄該廣播,截?cái)嘣搹V播傳遞下去。發(fā)送廣播的方法發(fā)送廣播sendOrderedBroadcast()方法方法格式如下:sendOrderedBroadcast(Intentintent,StringreceiverPermission,BroadcastReceiverresultReceiver,Handlerscheduler,intinitialCode,StringinitialData,BundleinitialExtras)方法中有七個(gè)參數(shù):intent,是一個(gè)Intent,是發(fā)送廣播的意圖對(duì)象,可以攜帶廣播信息;receiverPermission,是一個(gè)字符串,用于指定接收權(quán)限,如果為空,則不需要權(quán)限;resultReceiver,是一個(gè)廣播接收器,用于指出有序廣播的最終廣播接收者,該最終接收器可以不在清單文件中配置,仍會(huì)接收到廣播;scheduler,是一個(gè)線程,若傳null,則默認(rèn)是在主線程中;initialCode,是一個(gè)整數(shù),用于初始化的一個(gè)值。默認(rèn)值為Activity.RESULT_OK;initialData,是一個(gè)字符串,用于發(fā)送廣播的初始化數(shù)據(jù)(相當(dāng)于一條廣播數(shù)據(jù)),可為null;initialExtras,是一個(gè)Bundle,用于綁定數(shù)據(jù)傳遞(例如Intent對(duì)象extras數(shù)據(jù)),通常為null。發(fā)送廣播的方法發(fā)送廣播LocalBroadcastManager.sendBroadcast()方法LocalBroadcastManager.sendBroadcast()方法會(huì)將廣播發(fā)送給與發(fā)送器位于同一應(yīng)用中的接收器,即本地廣播。在Android4.0之后,將本地廣播封裝到LocalBroadcastManager類中。在使用方式上,本地廣播與全局廣播幾乎相同,只是注冊(cè)、發(fā)送、注冊(cè)廣播接收器時(shí)將主調(diào)context實(shí)例變成了localBroadcastManager實(shí)例。注意,從Android8.0版本開(kāi)始,對(duì)于靜態(tài)注冊(cè)的自定義廣播,在調(diào)用sendBroadcast()或sendOrderedBroadcast()方法之前,一定要先指定intent參數(shù)的所在包名,否則廣播無(wú)法發(fā)送給接收器。動(dòng)態(tài)注冊(cè)的廣播接收器不需要調(diào)用此方法。發(fā)送廣播的方法發(fā)送廣播設(shè)計(jì)思路本例自定義三個(gè)BroadcastReceiver,其中第一個(gè)接收器使用靜態(tài)方式注冊(cè),接收信息后分別向狀態(tài)欄和Toast提示消息區(qū)發(fā)送廣播;第二個(gè)接收器使用動(dòng)態(tài)方式注冊(cè),只向Toast提示消息區(qū)發(fā)送廣播,并向下一個(gè)接收器傳遞信息;第三個(gè)接收器是在發(fā)送有序廣播時(shí)作為最終接收者。本例應(yīng)用需要定義4個(gè)類實(shí)現(xiàn)代碼,一個(gè)類是Activity,在該類中定義用戶界面的交互、用于動(dòng)態(tài)注冊(cè)和注銷廣播接收器,在按鈕的onClick()方法中使用sendBroadcast()、sendOrderedBroadcast()方法發(fā)送廣播。另外3個(gè)類是BroadcastReceiver的子類,在子類中重寫onReceive()方法,用于定義接收器接收到廣播Intent傳遞的信息之后的各種操作?!景咐?0.3】通過(guò)兩個(gè)按鈕,一個(gè)按鈕發(fā)出一個(gè)無(wú)序廣播,另一個(gè)按鈕發(fā)出有序廣播。要求分別將廣播信息發(fā)送到狀態(tài)欄和頁(yè)面的Toast提示消息中;并且有序廣播接收器要傳遞信息到下一個(gè)接收器。開(kāi)發(fā)步驟準(zhǔn)備圖片資源。將用于通知的圖標(biāo)的圖片資源復(fù)制到本項(xiàng)目的res/drawable目錄中。設(shè)計(jì)布局。在res/layout目錄下編寫activity_main.xml布局文件。開(kāi)發(fā)邏輯代碼。靜態(tài)注冊(cè)設(shè)置。在AndroidManifest.xml中注冊(cè)第一個(gè)廣播接收器。發(fā)送廣播在AndroidManifest.xml中注冊(cè)第一個(gè)廣播接收器代碼片段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ā)送無(wú)序廣播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個(gè)接收器,接收到廣播消息。";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個(gè)接收器\n"+intent.getStringExtra("msg"),50Toast.LENGTH_LONG);51tt1.setGravity(Gravity.TOP,0,650);52tt1.show();53Log.e(TAG,"onReceive:"+"第1個(gè)廣播接收器");54 55}56}發(fā)送廣播MyBcReceiver2.java代碼片段1publicclassMyBcReceiver2extendsBroadcastReceiver{2 3@Override4publicvoidonReceive(Contextcontext,Intentintent){5Toasttt2=Toast.makeText(context,6"這是第2個(gè)接收器\n"+intent.getStringExtra("msg")+"\n并傳遞消息",7Toast.LENGTH_LONG);8tt2.setGravity(Gravity.CENTER,0,200);9tt2.show();10 11Log.e(TAG,"onReceive:"+"第2個(gè)廣播接收器,并傳遞消息");12 13Bundlebundle=newBundle();14bundle.putString("first","第2個(gè)接收器傳遞的消息啦!!!");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個(gè)接收器\n"+message+"\n\n"12+"同時(shí)接收到第2個(gè)接收器傳來(lái)的消息:"+first,Toast.LENGTH_LONG);13tt3.setGravity(Gravity.BOTTOM,0,120);14tt3.show();15 16Stringss="onReceive:"+"第3個(gè)廣播接收器,并接收第2個(gè)接收器傳出的消息"+first;17Log.e(TAG,ss);18 19}20 21}MyBcReceiver3.java代碼片段發(fā)送廣播運(yùn)行結(jié)果(a)發(fā)送無(wú)序廣播(b)向下拉開(kāi)通知欄(c)發(fā)送有序廣播由于在API30以上的模擬器中,Toast的setGravity()方法失效,本例在API29模擬器中運(yùn)行。Android后臺(tái)線程PART.03Android后臺(tái)線程線程是比進(jìn)程更小的執(zhí)行單位。開(kāi)發(fā)Android應(yīng)用時(shí)必須遵守單線程(Single-threaded)模型的原則。當(dāng)一個(gè)程序第一次啟動(dòng)時(shí),Android會(huì)啟動(dòng)一個(gè)LINUX進(jìn)程和一個(gè)主線程(MainThread)。主線程主要負(fù)責(zé)處理與UI相關(guān)的事件,常被稱為UI線程。UI線程能根據(jù)用戶的要求做出快速響應(yīng),不宜占用太長(zhǎng)的時(shí)間。如果占用時(shí)間超過(guò)10秒,Android系統(tǒng)就會(huì)給用戶顯示ANR提示信息。Android系統(tǒng)將所有運(yùn)行慢的、耗時(shí)操作交給子線程,以解放UI線程,避免阻塞。線程Thread線程Thread所有非主線程就是子線程,子線程一般都是后臺(tái)線程,它是由用戶在程序中定義的。Thread類位于java.lang.Thread包中。Thread類常用的方法。方法說(shuō)明run()包含線程運(yùn)行時(shí)所執(zhí)行的代碼start()用于啟動(dòng)線程sleep(longmillis)線程休眠,以毫秒為單位。線程休眠時(shí)交出CPU,讓CPU去執(zhí)行其他的任務(wù),然后線程進(jìn)入阻塞狀態(tài),sleep方法不會(huì)釋放鎖yield()使當(dāng)前線程交出CPU,讓CPU去執(zhí)行其他的任務(wù),但不會(huì)是線程進(jìn)入阻塞狀態(tài),而是重置為就緒狀態(tài),yield方法不會(huì)釋放鎖currentThread()獲取當(dāng)前線程。是靜態(tài)方法,返回值為當(dāng)前線程interrupt()中斷線程。注
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 軟件開(kāi)發(fā)程序員勞動(dòng)合同
- 食堂經(jīng)營(yíng)飲食承包合同
- 自行車制造許可合同
- 茶具行業(yè)展會(huì)組織與策劃合同
- 廠房租賃合同附帶員工培訓(xùn)與職業(yè)發(fā)展規(guī)劃
- 離婚贍養(yǎng)費(fèi)及子女撫養(yǎng)金支付管理合同
- 三氟甲基取代對(duì)化合物活性影響的多維度探究:統(tǒng)計(jì)與計(jì)算化學(xué)視角
- 萬(wàn)箱船輪機(jī)模擬器:虛擬設(shè)計(jì)架構(gòu)與通信技術(shù)實(shí)現(xiàn)探究
- 房地產(chǎn)市場(chǎng)的區(qū)域分化與2025年綠色建筑投資策略分析
- 旅游目的地的旅游市場(chǎng)培育與游客增長(zhǎng)策略報(bào)告
- 醫(yī)院培訓(xùn)課件:《住院患者VTE風(fēng)險(xiǎn)評(píng)估及預(yù)防》
- 2024年6月英語(yǔ)四級(jí)考試真題及答案(第1套)
- 新思想引領(lǐng)新征程新青年建功新時(shí)代-(第二版)
- 基本公共衛(wèi)生服務(wù)培訓(xùn)計(jì)劃
- 《業(yè)務(wù)員培訓(xùn)》課件
- 2024中國(guó)糖尿病合并慢性腎臟病臨床管理共識(shí)解讀
- 寺院承包合同范例
- GB/T 44575-2024抗沖擊聚苯乙烯(PS-I)擠出片材要求和試驗(yàn)方法
- 2024年山東省青島市中考語(yǔ)文試卷(含答案解析)
- 口腔護(hù)理保健課件
- 云南省部分學(xué)校2024-2025學(xué)年高三上學(xué)期9月聯(lián)考試題 生物 含答案
評(píng)論
0/150
提交評(píng)論