安卓平板的ttl在哪裡找
A. 移動應用開發需要學什麼
經過參與各種各樣的移動項目,我總結出一些要考慮的方面。當你設計或構建一個移動應用時候,需要把它們記在腦中。
移動app開發考慮的方面
認證層(Authentication Layer)
這應該是你開發鏈中的第一步。為了應對各種各樣的認證請求與inflight request,這一層應該有足夠可擴展性。需要留意認證令牌的刷新,令牌刷新失敗或類似情況時的錯誤處理。
自動編譯
要確保你為安卓和iOS建立了一個能自動編譯的安裝程序,並且有把他們分配給測試者的渠道。
舒適的移動體驗
如果因為一些原因,即使是沒有網路或者api停止工作了,也需要保證用戶能夠返回並從app退出。用戶應該總能夠點擊到導航欄,這樣還能夠進入緩存中的頁面,注銷,當網好的時候重新載入,或退出app等。一定避免用戶不得不強行終止app進程的情況。這是需要提前考慮的另一個設計特點。
數據封裝
當設計數據封裝時候一定要考慮API的存留時間(ttl),用默認的ttl,緩存層,採用多數據源傳送以標准表或者鍵值存儲的數據。
推出更新
如果app的數據頻繁改變,人們想要看到更新的消息,那麼這個特性會很有用。這對於那些展示實時事件更新的app很需要。
崩潰分析
把崩潰分析與app聯系起來非常重要,這樣如果用戶的app崩潰了,我們就能知道原因並可以更快的在下個版本修復。許多工具都可以做到這些。
數據存儲
從app設計出發,這是需要考慮的最重要方面。有很多種在手機中存儲數據的方法。比如WebStorage(LocalStorage, SessionStorage) , InMemory, SQLite. Localstorage的大小是10MB,如果你的要存的數據比這個小,它是個好選擇。它的缺點之一是,當你的內存滿了以後,操作系統會清空Localstorage數據。SQLite是基於文件的資料庫,而且對於更大的文件更加穩定。它是嵌入式關系型資料庫,如果你想把大量數據存儲/緩存在客戶端,它會是你的好朋友。
導航堆棧
當需要在不同頁面間導航,並且有不止一種入口可以到達需要的頁面時,它就是app最重要特性之一。它同樣可以被分為不同的導航堆棧,比如:App導航,Tab導航,菜單導航等。要時刻考慮到各種情況,這樣用戶就不會陷入循環依賴 (死胡同)而需要強制停止app。
網路連接
開者經常假定人們總是有良好的互聯網,按照這個邏輯設計app並把它推出。這也是當app不工作或不能持續下載數據時,大部分新手開發者受到打擊的一點,最終導致了app在apple/google商店的低評價。一旦app已經推出,修復這類問題就很不容易,需要大量的退化。所以設計app時,這是需要考慮的重要一點。
檢查平台
別忘了這個app是建立在哪種平台上的。保證所有的開發者/測試者都在機器上安裝了相關程序,並且把這些程序列入文檔,這樣任何新來的開發者都可以很快掌握。要清楚開發者和測試者要怎樣進行測試。
對於安卓,至少需要安裝Android Studio, Gradle.
對於iOS你需要創建簽名請求來生成證書,還有配置文件。(如果你事先不知道它至少花費一天,你會覺得這個過程很長。建議去找已經做過這一步的人,這一步就會縮減到15分鍾)。不管你用哪種架構,要進行iOS開發你都需要至少一個Mac和iPhone。
付費
如果你的app需要付費,需要遵照Google和蘋果付費規則文件。注意:你同樣需要建立一些後端,這樣當用戶為你的app付費時候就可以去處理收據,並且你需要在伺服器端保存這些單據。
本地特性
用列表列出app上需要本地設備支持的特性。例如:相機,狀態欄,定位服務,通知等。並檢查這些支持是否提供給了框架內所有內容。
推送服務
如果你的app需要推送服務,提前決定你要用哪家服務。檢查針對選擇的框架所用的插件是否有效。第一次用iOS測試這些時,為了讓設備接收推送,需要添加一個app證書。同樣也要決定你需要基於主題推送還是基於設備。
B. 安卓開發音頻mic口怎麼接收20khz的波形
安卓開發音頻mic口接收20khz的波形的方法?
一、手機音頻通信的特點
1、 通用性強:在智能手機普及的今天,手機的對外通信介面多種多樣,而其中以3.5mm的音頻介面通用新最強,基本所有的手機、平板電腦都會有這個介面,所以在一些要求通用性的設備上,音頻介面登上了舞台。
2、 速率低:由於手機音頻部分的采樣頻率一般為44.1KHZ(部分國產山寨為8KHZ),這極大的限制了音頻通訊的速率。我們都知道44.1KHZ的采樣頻率,那麼最高的信號頻率只能為20KHZ左右,而信號周期也不可能只有2個采樣點,通常要到10個以上,這樣層層下來通訊速率可想而知。
3、 小信號:音頻通信的信號都是毫伏級的,各個手機廠商略有不同,但通常最大不超過200mv,通常我們通信使用的信號強度也就100mv左右,這導致信號比較容易受干擾,且在開發階段對工具有著種種限制。
二、 手機音頻通信分類
1、 無線方式:
a) 無線方式大家可能不太熟悉,容我慢慢道來。我們都知道人耳能聽到的聲音頻率為20HZ~20KHZ,而手機通信的信號頻率最高也就20KHZ,所以無線通信方式是可行的。因為雖然人耳的極限聽力能到20KHZ,但普通人一般在19KHZ以上時基本就聽不到了,所以如果信號的強度比較弱,且控制在19KHZ到20KHZ之間,那麼我們就可以將之當做是「超聲波」來看待了。
b) 其實在此提到手機音頻通信的無線方式,算是給大家一種產品開發思路吧。它的通訊半徑在10M左右,前景還是很廣闊的,大家有興趣的可以試試。(其實已經有這方面的產品了)
2、 有線方式:
a) 有線方式分為單向(設備→手機)和雙向兩種,單向的限制少,開發難度也小一些,但實際應用時會受限制。而雙向通信限制多,開發難度也大一些,但實際應用時更方便些。
b) 設備→手機:曼徹斯特編碼;FSK;DTMF;自定義正弦波
c) 手機→設備:由於手機輸出的音頻信號很小,無法直接使用,要麼用運放發大到合適的范圍,要麼用電壓比較器轉換成TTL方波。
三、手機音頻通信硬體通信方式分類:手機音頻通信的硬體通信方式大體可分為方波和正弦波兩種。
1、 方波:方波通常使用的是曼徹斯特編碼方式(什麼是曼徹斯特編碼自己去查),它的好處是可以用單片機直接輸出方波,經過衰減後即可使用,方便簡單。缺點是兼容性不好,因為手機音頻部分有這樣一個特性,它只識別變化的電平信號,當麥克輸入的信號長時間保持在某一非零電平時,手機會將其視為零,而強行拉回零電位。這就是採用方波通訊方式的兼容性不好的最大原因了,並且方波也容易受干擾。
2、 正弦波:正弦波不會出現上面所說的方波的問題,故正弦波的兼容性和穩定性更好一些。通常採用方案有FSK、DTMF、信號發生器、或方波轉正弦波等。(後面會對以上方案逐一分析)
3、 通信信道分析
a) 我們知道音頻介面有4根線,MIC、地、左、右聲道。設備→手機用MIC,手機→設備用地、左、右聲道中的任意一個。這里說一下,實際產品中,有一些廠家會更換地線,即將原本左、有聲道中的一根改為地線來用,其實道理是一樣的。因為音頻通信的信號時交流信號,而地其實也是懸浮地,即便地線換了,最終的波形還是一樣的,因為最終手機解析信號時需要的是頻率和幅值。這樣還剩下一個聲道,通常被用來幫助設備進行上電識別,因為音頻通信的設備通常都是電池供電的。
b) 另外還要在MIC和地之間並聯一個4.99K的電阻,因為手機是通過檢測MIC和地之間的阻抗是否為4.99K(也有其他阻值的)來判斷是否有設備(耳機)插入,這一點要謹記。
四、各個通信方案對比分析
1、 設備→手機:
a) 曼徹斯特編碼:在諸多通信方式中,曼徹斯特編碼是最靈活簡便的一種方法,編碼信號可由單片機直接產生,經衰減電路衰減後便可直接使用。注意事項:曼徹斯特編碼信號的生成有兩種方式,一種是用PWM生成,一種是用定時器中斷翻轉IO,我個人比較傾向於定時器中斷方式。因為我們知道曼徹斯特編碼中有寬沿河窄沿之分,且寬沿和窄沿可能會靈活變化,而用PWM方式不容易精確控制寬沿、窄沿輸出的變化,而定時器中斷方式則非常靈活且容易控制。(後面會送上我自己寫的曼徹斯特編碼、解碼函數)
b) FSK、DTMF方式:FSK和DTMF兩種方式大同小異,使用時通常都是用集成的晶元來生成的,而這些晶元通常都是遵守固定的通信協議的的要求(FSK為Bell202或V.23協議,DTMF記不清名字了)。這兩種通信方式的優點是採用正弦波通信、穩定性好且使用簡便。但由於固定通信協議的限制導致通信速率、比特率也受到限制而缺乏靈活性。在這里跟他家推薦一款英國的通信晶元CMX系列,這個系列的晶元融合的FSK、DTMF的編碼、解碼,還是很不錯的,大家有興趣可以試試。(相關手冊在附件里)
c) 信號發生器、鎖相環方式:這種方式用信號發生器或者鎖相環來產生方波或正玄波,由單片機來控制波形的輸出,也可以實現音頻通信,且十分靈活。但缺點是電路較復雜,且不同頻率信號之間銜接不好掌握,用不好反而是麻煩。(相關手冊在附件里)
d) 在這里送上一種我個人認為比較好的方案:就是曼徹斯特編碼加低通濾波器,由單片機輸出曼徹斯特編碼,再經由低通濾波器將方波濾成正弦波後輸出。既解決了FSK、DTMF靈活性的問題,又解決了曼徹斯特編碼方波穩定性、通用性的問題。在低通濾波器方面我個人採用的是「集成低通開關電容濾波器」,它成本雖然高一些,但好處也是明顯的,電路簡單,使用方便,且佔用的空間亦很小。(相關手冊在附件里)
2、 手機→設備:
a) 放大電路方式:將手機輸出信號經放大電路放大到合適的幅值,然後有鎖相環或者結成FSK、DTMF晶元進行解析。該中方式難度最大,需要非常強的模擬電路功底,我個人水平有限,故採用的另一種方式。
b) 電壓比較器方式:將手機輸出的交流信號經電路強行拉到Vcc/2級別,然後加到電壓比較器一端,另一段接比較電壓Vcc/2,這樣交流信號即被轉化為TTL方波信號,此時再進行解析就變得很簡單了。
五、研發注意事項(通訊方案分析部分由於過長,放到最後來講)
1、 一個好手機錄音軟體是必須的,最好能在手機上直接看到波形的。
2、 建議用筆記本電腦進行開發,而非台式機。因為音頻信號很小,容易受干擾,而台式機干擾較大,筆記本還有一個好處是必要時可將外接電源拔掉,用電池供電。
3、 一個好錄音筆必不可少,有時需要得到純凈的音頻信號,方便更加准確的分析。
4、 做一個轉接板,一邊接音頻母座,一邊接音頻公頭,將MIC、地、左、右聲道4跟線用排陣引出,方便錄音。
5、 做一個信號衰減電路,可將設備電路產生的信號衰減至音頻介面能承受的范圍內。前期調試時,我們可以用該電路將信號錄進電腦進行信號分析。(推薦一個電腦音頻信號分析軟體:Goldwave)
6、 錄音用的音頻線切記不要太長,不然會給你帶來不少麻煩。最好自己做,用音頻裸頭、杜邦線、排陣即可製作,方便好用。
曼徹斯特編碼的編碼解碼函數如下:
/**********************************************************************
注釋:編碼函數都是採用定時器中斷的形式,以曼徹斯特編碼的窄沿作為定時器周期。
發送的數據包括1個起始位、8個數據位、1個奇偶校驗位、3個停止位。
***********************************************************************/
static void VIC_VECT_Fucton_00(void)//發送編碼數據中斷函數
{
TIMER0IS =0x0;
if((send_time%2==0) && (send_start==1))
{
switch(FSK_txState)
{
case STARTBIT:
if((GPIODATA&0x00000002)==0x00000000)//如果檢測到數據發送管腳為零
send_time++;
else
{
currentSym=0;
FSK_txState = BYTE;
}
break;
case BYTE:
if(txBit < 8)
{
currentSym = (send_byte >> txBit) & 0x01;
txBit++;
txParity += currentSym; //奇偶校驗位
}
else if (txBit == 8)
{
currentSym = txParity & 0x01; //發送奇偶校驗位
txBit++;
}
else if(txBit>8 && txBit<12)
{
// next bit is the stop bit
currentSym = 1; //發送停止位
txBit++;
}
else if(txBit == 12)
FSK_txState = STOPBIT;
break;
case STOPBIT :
txBit=0;
FSK_txState=IDLE;
send_start=0;
txParity=0;
send_byte=0;
break;
}
if(lastSym!=currentSym)
{
timer1_num++;
lastSym=currentSym;
}
}
if(timer1_num%2==0)
GPIODATA&=0xFFFFFFFD;//輸出管腳復位
else
GPIODATA|=0x00000002;//輸出管腳置位
timer1_num++;//用來控制IO口的電平翻轉
send_time++;//用來控制發送的位元組的每一位
Delay++;//Delay就是延時函數
}
/**********************************************************************
注釋:解碼函數採用外部IO中斷形式(上升沿或下降沿中斷,即電平電平跳變中斷),
用一個定時器作為時鍾,每次產生中斷時便從定時器見時間值取出,並和上一次的
記錄做差求出時間間隔,以此來判斷當前為寬沿還是窄沿。
***********************************************************************/
static void VIC_VECT_Fucton_04(void)//接受解碼數據中斷函數
{
GPIOIC|=0x00000001;//清楚上一次中斷內容
RX_time=TIMER1VALUE;
if(RX_lasttime>=RX_time)
RX_diff=RX_lasttime-RX_time; //lasttime初始值為0
else
RX_diff=65535-RX_time+RX_lasttime;
RX_lasttime=RX_time;
switch(RX_state) //啟動代碼時state已經被配置為STARTBIT
{
case STARTBIT_FALL:
if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))
{
if(RX_ones<5) //ones初始值為0
{
RX_ones = 0;
}
else
{
RX_state = DECODE; //將狀態配置為解碼
}
}
else if(RX_diff < SHORTINTERVAL)
RX_ones++;
else
RX_ones=0;
break;
case DECODE:
/**************通過間隔長短來判定數據**************/
if ((SHORTINTERVAL<RX_diff) && (RX_diff<LONGINTERVAL))// 若間距在范圍內則當前數據位值和前一個相反
{
currentbit=(currentbit+1)&0x01;
RX_times+=2;
}
else if( RX_diff < SHORTINTERVAL)
{
currentbit=currentbit;
RX_times++;
}
else
RX_state = DATAINIT;
/****************接受數據位,從低位接起****************/
if(RX_times%2==0)
{
if(RX_bitcounter<8)
{
if (currentbit==1)
{
uartByteRx = (uartByteRx >> 1) + (1<<7);
rxParity++; //奇偶校驗位
RX_bitcounter++; //接受數據位數
}
else
{
uartByteRx = (uartByteRx >> 1);
RX_bitcounter++;
}
}
else
{
rxParity&=0x01; //進行奇偶校驗
if(rxParity==currentbit)
{
RX_bitcounter++;
RX_finish=1;
RX_state=DATAINIT;
}
else
RX_state=DATAINIT; //若奇偶校驗錯誤則,重新檢測
}
}
break;
case DATAINIT : //初始化參數狀態
RX_bitcounter=0;
RX_ones=0;
rxParity=0;
currentbit=0;
RX_state=STARTBIT_FALL;
RX_times=0;
break;
default:
break;
}
}