這個(gè)是onCreate里面的代碼
創(chuàng)新互聯(lián)建站是專業(yè)的新邱網(wǎng)站建設(shè)公司,新邱接單;提供網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行新邱網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
// 注冊(cè)接收新消息的監(jiān)聽(tīng)廣播
msgReceiver = new NewMessageBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(EMChatManager
.getInstance().getNewMessageBroadcastAction());
intentFilter.setPriority(3);
registerReceiver(msgReceiver, intentFilter);
下面是自己寫(xiě)的廣播里的操作
private class NewMessageBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// 注銷廣播
abortBroadcast();
// 消息id(每條消息都會(huì)生成唯一的一個(gè)id,目前是SDK生成)
String msgId = intent.getStringExtra("msgid");
EMMessage message = EMChatManager.getInstance().getMessage(msgId);
String news = ((TextMessageBody) message.getBody()).getMessage();
// 發(fā)送人id
String userId = intent.getStringExtra("from");
username = userId;
Info info = new Info();
info.setText(news);
info.setId(msgId);
info.setUserid(userId);
list.add(info);
}
}
因?yàn)檫@個(gè)系統(tǒng)廣播在不停的發(fā)送,系統(tǒng)網(wǎng)絡(luò)狀態(tài)在不停的變化。比如關(guān)閉,打開(kāi),掃描,正在連接,已連接等狀態(tài)。
如果你的項(xiàng)目需要監(jiān)聽(tīng)到開(kāi)機(jī)廣播,以此實(shí)現(xiàn)開(kāi)機(jī)自啟等類似功能,你到網(wǎng)上搜索一下,基本上都是搜到以下實(shí)現(xiàn)方法。
親測(cè)以上方法在我的一加5(Android 9)上是不管用的,其他博主給出的在第2步添加對(duì)SD卡加載完成等事件的廣播監(jiān)聽(tīng)方法,也是沒(méi)有任何效果,一直不太明白網(wǎng)上大家都給出的一致方法,為啥就沒(méi)效果了,難道是Android在后來(lái)的系統(tǒng)版本中,對(duì)這一塊做了改動(dòng)?直到前段時(shí)間看到了《Android開(kāi)發(fā)藝術(shù)探索》中關(guān)于廣播的發(fā)送和接受過(guò)程的一段講解,終于解開(kāi)了我的疑惑,原文摘抄如下:
通過(guò)上面這段話,我們可以知道,如果想讓廣播能夠發(fā)送到未啟動(dòng)的應(yīng)用,必須為廣播的Intent添加FLAG_INCLUDE_STOPPED_PACKAGES標(biāo)記,但是開(kāi)機(jī)廣播是系統(tǒng)發(fā)出的,我們無(wú)法修改。綜上所述,自Android3.1之后,App開(kāi)機(jī)自啟無(wú)法實(shí)現(xiàn)。
可以通過(guò)NotificationListenerService來(lái)監(jiān)聽(tīng)通知欄。NotificationListenerService是通過(guò)系統(tǒng)調(diào)起的服務(wù),在應(yīng)用發(fā)起通知時(shí),系統(tǒng)會(huì)將通知的應(yīng)用,動(dòng)作和信息回調(diào)給NotificationListenerService。但使用之前需要引導(dǎo)用戶進(jìn)行授權(quán)。使用NotificationListenerService需要下面三個(gè)步驟。
1、注冊(cè)服務(wù):
首先需要在AndroidManifest.xml對(duì)service進(jìn)行注冊(cè)。
2、繼承實(shí)現(xiàn)NotificationListenerService
自己實(shí)現(xiàn)一個(gè)繼承NotificationListenerService的service,在onNotificationPosted中完成自己需要的操作。
3、引導(dǎo)用戶進(jìn)行授權(quán)
由于此服務(wù)需要用戶手動(dòng)進(jìn)行授權(quán),所以使用前需要對(duì)用戶進(jìn)行引導(dǎo)設(shè)置。
這里的廣播是指你app里的廣播還是手機(jī)系統(tǒng)的廣播。
如果是你自己手機(jī)的app的廣播,你是否有注冊(cè)監(jiān)聽(tīng)廣播。
如果是手機(jī)系統(tǒng)的廣播,因?yàn)橐郧八械腶pp開(kāi)啟及運(yùn)行,都以監(jiān)聽(tīng)手機(jī)開(kāi)機(jī)廣播,后來(lái)開(kāi)發(fā)商直接攔截,不讓app監(jiān)聽(tīng)手機(jī)開(kāi)機(jī)等廣播。
我們做項(xiàng)目的時(shí)候,不可避免的要做網(wǎng)絡(luò)狀態(tài)的監(jiān)聽(tīng),一般我們都是抽取出一個(gè)工具類來(lái)實(shí)現(xiàn),比如:
細(xì)致的你當(dāng)然還會(huì)再寫(xiě)一個(gè)判斷網(wǎng)絡(luò)類型的方法,反手再來(lái)一個(gè)例:
然后就可以在相應(yīng)的操作前進(jìn)行判斷網(wǎng)絡(luò)的判斷:
但是這樣做也有些問(wèn)題:
接下來(lái)就是本文的重點(diǎn),如何通過(guò) NetStatusBus 這個(gè)庫(kù)來(lái)解決以上問(wèn)題,讓你的網(wǎng)絡(luò)狀態(tài)監(jiān)聽(tīng)變得前所未有的簡(jiǎn)單粗暴。
到這里就已經(jīng)結(jié)束了,你的所有網(wǎng)絡(luò)操作已經(jīng)都可以清晰優(yōu)雅的在訂閱方法中進(jìn)行處理了,當(dāng)然你也可以繼續(xù)往下看。
訂閱方法必須填寫(xiě)一個(gè)NetType參數(shù),可以通過(guò)NetType的值來(lái)判斷當(dāng)前網(wǎng)絡(luò)類型。
@NetSubscribe中 netType為可選值,可以設(shè)置訂閱的類型,可選值類型如下:
NetType.AUTO
這是默認(rèn)值,任何網(wǎng)絡(luò)狀態(tài)發(fā)生變化,該類型訂閱者都會(huì)被回調(diào)。同時(shí)會(huì)傳入NetType參數(shù)告知你當(dāng)前的網(wǎng)絡(luò)類型,示例如下:
只要當(dāng)前是由 WIFI 改變引發(fā)的網(wǎng)絡(luò)狀態(tài)變化,該類型訂閱者都會(huì)被回調(diào)。同時(shí)會(huì)傳入NetType參數(shù)告知你當(dāng)前的網(wǎng)絡(luò)類型,示例如下:
只要當(dāng)前是由移動(dòng)網(wǎng)絡(luò)改變引發(fā)的網(wǎng)絡(luò)狀態(tài)變化,該類型訂閱者都會(huì)被回調(diào)。同時(shí)會(huì)傳入NetType參數(shù)告知你當(dāng)前的網(wǎng)絡(luò)類型,示例如下:
NetType.NONE
只有當(dāng)網(wǎng)絡(luò)丟失時(shí),該類型訂閱者才會(huì)被回調(diào)。
有人會(huì)覺(jué)得,我用個(gè)庫(kù)爽就行了管它的原理干什么?
你放心,我只是小小的描述一下實(shí)現(xiàn)方式。
原理簡(jiǎn)單來(lái)說(shuō),就是在全局初始化的時(shí)候就綁定對(duì)網(wǎng)絡(luò)的變化監(jiān)聽(tīng)。然后將進(jìn)行注冊(cè)的父類所有的訂閱方法保存至集合中,這里涉及到一些方法的校驗(yàn),最后在網(wǎng)絡(luò)狀態(tài)發(fā)生改變時(shí)利用 Java 反射機(jī)制遍歷執(zhí)行所有訂閱方法。熟悉 EventBus 的小伙伴已經(jīng)看出來(lái)了這里借鑒了一小部分 EventBus 的思想。
回到第一步,那么具體是如何綁定對(duì)網(wǎng)絡(luò)狀態(tài)變化的監(jiān)聽(tīng)呢?
以前我們是通過(guò)注冊(cè)廣播來(lái)實(shí)現(xiàn)綁定網(wǎng)絡(luò)變更的監(jiān)聽(tīng),在Android 7.0 以后,Google 基于性能和安全原因?qū)V播進(jìn)行了很多限制,比如監(jiān)聽(tīng)網(wǎng)絡(luò)變更的廣播 android.net.conn.CONNECTIVITY_CHANGE 使用靜態(tài)注冊(cè)的方式則無(wú)法生效,而動(dòng)態(tài)注冊(cè)的方式雖然可以生效但畢竟不是最優(yōu)解。
同樣出于性能和安全,以及擁抱變化的角度,最終我們還是使用官方推薦的方式,利用 ConnectivityManager.NetworkCallback 來(lái)進(jìn)行網(wǎng)絡(luò)變化的監(jiān)聽(tīng),這是在Android 5.0即android api 21推出的API,目前Android 5.0以上的市場(chǎng)占有率在 85%以上,隨著國(guó)內(nèi)各大廠商正在積極的推進(jìn)適配普及Android Q,這個(gè)比例還會(huì)進(jìn)一步增大,所以個(gè)人人認(rèn)為無(wú)需過(guò)于擔(dān)心低版本適配。
使用的時(shí)候出現(xiàn)這個(gè)問(wèn)題是由于少添加了權(quán)限。
Caused by: java.lang.SecurityException: ConnectivityService: Neither user 10513 nor current process has android.permission.ACCESS_NETWORK_STATE.
java.lang.RuntimeException: Unable to create application com.jiyun.wanandroid.WanApplication: java.lang.SecurityException: ConnectivityService: Neither user 10513 nor current process has android.permission.ACCESS_NETWORK_STATE.
加上這幾個(gè)權(quán)限就好了:
附上原文地址: