㈠ android判斷主線程是否阻塞
android判斷主線程是否阻塞可以這么做:如果內部緩沖區中有足夠多的音頻樣本,則read()會立即返回數據.如果還不夠,則read()等待直到有,然後返回數.()可用於設置監聽器,而.setPositionNotificationPeriod()和.setNotificationMarkerPosition()可分別用於設置通知Period和Position.
㈡ android 串口讀數導致界面卡死
需要用子線程去讀取數據,當數據讀取完成,通過handler 發送一個消息讓主線程去更新UI
㈢ Android廣播阻塞、延遲問題
最近項目中,多次碰到app研發人員反饋廣播從發送到接收器接收,間隔時間太長,要求系統進行優化,特別是開機階段。對此,專門閱讀了一下廣播從發送到接收這個流程的源碼,以徹底搞明白怎樣讓自己發送的廣播盡快到達接收器。
涉及到的源碼類不多,主要就是ActivityManagerService.java 和 BroadcastQueue.java。發送廣播進程調用發送介面,通過IPC到達AMS,AMS根據Intent是否配置Intent.FLAG_RECEIVER_FOREGROUND,選擇當前廣播加入前台廣播隊列還是後台廣播隊列。根據當前廣播是否有序,將廣播加入廣播隊列的串列列表還是並行列表。廣播隊列和廣播隊列中的廣播列表是影響廣播接收時間的主要因素。
BroadcastQueue廣播隊列,負責將廣播發送給廣播接收器。AMS中有兩個成員變數,
BroadcastQueue mFgBroadcastQueue;//前台廣播隊列
BroadcastQueue mBgBroadcastQueue;//後台廣播隊列
前台廣播隊列和後台廣播隊列的區別有兩處:1 超時時間,前台10s,後台60s. 2 是否延遲廣播等待前一個廣播進程完成。這兩個區別已經說明前台廣播對廣播接收器要求更高,響應時間更短,如果廣播要排隊,時間上前台廣播更短。同時系統默認使用後台廣播隊列,所以前台廣播隊列處理的廣播要少,避免了可能的大量廣播排隊情況。
廣播隊列中的列表
//存放無序並發送給動態廣播接收器的廣播任務
final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>();
//存放無序發送給靜態廣播接收器的廣播任務或者存放有序廣播任務
final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>();
mParallelBroadcasts 此列表中存放的是無序廣播動態廣播接收器任務,廣播隊列會在處理任務時通過嵌套循環,把每個廣播通過ipc發送到關注它的所有進程。所有無序廣播+動態廣播接收器,廣播不需要排隊。這種情況是最快能讓廣播到達目標進程的方式。
mOrderedBroadcasts存放的廣播任務特點:廣播有序,或者廣播接收器是靜態注冊的。此種類型的廣播全部要在mOrderedBroadcasts中排隊,廣播之間按時間先後,同一個廣播不同廣播接收器按優先順序。mOrderedBroadcasts存放的廣播必須等一個廣播任務處理完畢才能處理下一個,中間可能包含進程的啟動等。
由此可見,廣播最快的情況是前台廣播、無序廣播、動態注冊廣播接收器。最糟糕的情況是:後台廣播、有序或靜態注冊廣播接收器、廣播接收器優先順序低。如果一個應用只是簡單的靠注冊一個靜態廣播接收器拉起進程,對應的正是最糟糕的情況。如果又發生在開機階段,自然延遲嚴重。
如果必須注冊靜態廣播接收器,縮短時間的辦法為:配置Intent.FLAG_RECEIVER_FOREGROUND,加入前台廣播隊列,設置廣播優先順序
源碼:
廣播發送:Context .sendBroadcast ->ActivityManagerNative.broadcastIntent->ActivityManagerService.broadcastIntent->ActivityManagerService.broadcastIntentLocked.到此階段,跟發送廣播的進程通信結束。此階段AMS完成的工作主要是根據Intent查找該廣播對應的動態廣播接收器、靜態廣播接收器、以此發送該廣播使用的廣播隊列。
private final int broadcastIntentLocked(
......//許可權檢查
......//特殊系統廣播進行必要處理
if (sticky) {//粘性廣播處理
......
//查找靜態注冊的接收器
receivers = collectReceiverComponents(intent, resolvedType, users);
if (intent.getComponent() == null) {
// 查找動態廣播接收器
registeredReceivers = mReceiverResolver.queryIntent(intent,
resolvedType, false, userId);
}
//動態廣播接收器
int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
if (!ordered && NR > 0) {
//確定隊列
final BroadcastQueue queue = broadcastQueueForIntent(intent);
//創建廣播任務BroadcastRecord
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType, requiredPermission,
appOp, registeredReceivers, resultTo, resultCode, resultData, map,
ordered, sticky, false, userId);
......
//廣播任務加入並行列表中
queue.(r);
//啟動非同步發送廣播任務
queue.scheleBroadcastsLocked();
registeredReceivers = null;
NR = 0;
......
while (it < NT && ir < NR) {
......
//根據優先順序排序
if (curt == null) {
curt = (ResolveInfo)receivers.get(it);
}
if (curr == null) {
curr = registeredReceivers.get(ir);
}
if (curr.getPriority() >= curt.priority) {
// Insert this broadcast record into the final list.
receivers.add(it, curr);
//獲取廣播隊列
BroadcastQueue queue = broadcastQueueForIntent(intent);
//創建廣播任務
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
callerPackage, callingPid, callingUid, resolvedType,
requiredPermission, appOp, receivers, resultTo, resultCode,
resultData, map, ordered, sticky, false, userId);
//加入到廣播隊列串列列表中
queue.enqueueOrderedBroadcastLocked(r);
//啟動非同步發送任務
queue.scheleBroadcastsLocked();
廣播隊列處理廣播:
final void processNextBroadcast(boolean fromMsg) {
......
//並行列表,遍歷廣播任務
while (mParallelBroadcasts.size() > 0) {
final int N = r.receivers.size();
//遍歷接收器
for (int i=0; i<N; i++) {
//IPC調用發送給目標進程
(r, (BroadcastFilter)target, false);
}
}
//有串列廣播任務正在執行
if (mPendingBroadcast != null) {
//接收廣播的目標進程正常
if (!isDead) {
// It's still alive, so keep waiting 繼續等待目前進程反饋
return;
}
}
//取出第一個廣播
r = mOrderedBroadcasts.get(0);//判斷是否超時,
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {
//廣播超時
broadcastTimeoutLocked(false);//超時處理,終止當前廣播,啟動下一個任務。
}
if (r.receivers == null || r.nextReceiver >= numReceivers
|| r.resultAbort || forceReceive) {
//所有廣播任務執行完畢
}
int recIdx = r.nextReceiver++;//下一個廣播接收器
r.dispatchTime = r.receiverTime;//設置派發時間
setBroadcastTimeoutLocked(timeoutTime);//啟動超時計時
if (nextReceiver instanceof BroadcastFilter){//動態廣播接收器
(r, filter, r.ordered);//發送
return;
}
.//靜態廣播
ResolveInfo info =
(ResolveInfo)nextReceiver;
......
//檢查進程是否已啟動
ProcessRecord app = mService.getProcessRecordLocked(targetProcess,
info.activityInfo.applicationInfo.uid, false);
if (app != null && app.thread != null) { /進程啟動
processCurBroadcastLocked(r, app);//發送靜態廣播
return;
}
if ((r.curApp=mService.startProcessLocked(targetProcess,//啟動進程
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
"broadcast", r.curComponent,
(r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))
== null) {
//進程啟動失敗
}
//標志正在發送的串列廣播
mPendingBroadcast = r;
mPendingBroadcastRecvIndex = recIdx;//正在發送的廣播任務對應的接收器索引
}
㈣ 求教Android藍牙串口開發OutputStream發送數據失敗的問題
1、首先確保你發送的數據是正確的,串口接收到這個數據後他能識別,並返回你想要的數據,如果你發送的命令本身不要求返回數據,inputstream是讀取不到數據的。 2、其次,要確保發送數據的格式正確,比如一段16進制數據,你定義為String="01230545"類型,然後發送的時候out.write(str.getBytes());這樣發送的數據是不對的,應該定義一個byte型的數組,然後發送這個數組 3、以上你都確保沒問題了,你可以用循環去讀取數據,當讀到的內容大於0時停止讀取。用循環讀取你要確保你已經設置讀取的超時時間了,不然程序有可能阻塞。
㈤ Android讀串口數據阻塞怎麼辦
我這邊也在做Android和硬體設備的串口通信。
我的通信方式很簡單,我這邊發送數據,接收數據(接收數據的內容中有標識位讓我判斷這次接收到的數據的相應處理動作)
讀數據的時候我做的是一個清空的辦法,每一次讀取數據,如果讀到的數據准確則進行處理,如果有誤就清空了在讀。
如果說接收的數據要對應上發送的數據,你可以在Android這邊發送數據後不在發送數據只讀取,並開啟一個計時器,當這段時間內么有接收到返回值就繼續你的發送和讀取功能
㈥ android 串口為什麼不能正常讀寫
串口通讓游信枝滑攔數據丟失很大一部分原因是:mscomm的inputlen設置設置有問題;
解決方案:
mscomm的inputlen設置為0吧(讀取整個緩沖區),讀完一次,清空一次緩沖區試試;
參考如下:
猛胡窗體初始化事件中建議將mscomm的這幾個屬性做如下設置:
mscomm.inbuffersize=8 '接收緩沖區大小
mscomm.rthreshold=4 '促發oncomm事件的字元數
mscomm.inputlen=0 '默認讀取整個緩沖區
mscomm.inputmode=cominputmodetext '以文本方式接收
mscomm.inbuffercount=0 '清空緩沖區
oncomm事件中,建議處理完接收數據後用mscomm.inbuffercount=0清空緩沖區
㈦ 串口ReadFile讀取數據一直有阻塞,即使有數據上來,該怎麼解決
串口同步讀寫數據,ReadFile會一直阻塞,但是用串口調試助手可以接受到數據。 不過之後再啟動程序就正常了,很郁悶,不知道問題出現在哪裡,下面把代碼貼出來: 以同步方式打開串口: bool CSerialIO::openSerialPort(char* szSerial){HANDLE hSerial=CreateFileA(szSerial, GENERIC_READ|GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if(INVALID_HANDLE_VALUE==hSerial) return false; this->hComm=hSerial; memcpy(cComm,szSerial,strlen(szSerial)); cComm[strlen(szSerial)]='\0'; return true;}讀串口:unsigned WINAPI RecieveData(void* pProcessData){ProcessData* pPD=(ProcessData*)pProcessData;while(1){if(pPD->bClosePushThread==true) ExitThread(0); byte byteTempBuffer[512]={0}; int iRead=0; if(pPD->pSerialIO->readSerialPort(byteTempBuffer,511,iRead)){if(iRead<=0){Sleep(1000);continue;}else{pPD->critSecData.lock(); pPD->bVectorRawData.insert(pPD->bVectorRawData.end(),byteTempBuffer,byteTempBuffer+iRead); pPD->critSecData.unLock();continue;}}Sleep(1000);}return 0;}這是一個線程入口函數,pPD->pSerialIO->readSerialPort(byteTempBuffer,511,iRead)這句代碼實際上就是調用ReadFile來讀串口數據,在這里設個斷點,每次進入這個線程都會阻塞在這個地方,但是如果我用下串口調試助手後,就不會出現這個問題,也就是說 我要讀寫的串口必須要先被其他的進程讀寫過,然後才能正常運行。 ps:不要建議我非同步讀寫串口,因為我現在問題還沒解決。不知道是不是還需要對串口的參數進行設置。 再說下重點,我的程序可以正常運行的前提是:程序運行之前,用過串口調試助手之類的,也就是說必須要利用別的程序對串口的參數進行設置我的程序才能正常運行。
㈧ 串口通訊接收線程為阻塞方式,怎麼關閉串口
另一個線程完全可以運行,是否運行決定權在你。
如果另一個線程需要等待串口的數據,那麼它應該調用wait來等待信號量
讀取串口數據的線程應該在讀取完成後通知等待在信號量上的線程,以繼續運行。
㈨ Android讀串口數據阻塞怎麼辦
另一設備也是你可以修改開發的或攔嗎 弄跳停止命令或者空命令,發下去之後,有特定數據上來給你讀,讀到之後,就別在讀就可以了 再研究研究 PC上的話罩滑,好像沒遇到阻塞情況,或者真的有數據上來給讀,忘記了,USB阻塞倒是遇到過,最後就是弄了個停止命令,這種硬體阻塞的最NB了,藍屏,各種無法結束進程,呵呵 安卓物團臘平台的,不了解 等大神