Android USB通信

1:簡介:

?????????? 自Android3.1(API Level 12)版本開始,Android系統(tǒng)直接支持USB配件(Accessory Mode)和USB主機(jī)(Host Mode)兩種模式支持各種USB外圍設(shè)備和Android USB配件(實現(xiàn)Android配件協(xié)議的硬件)戴尸。

注意:以上關(guān)于Android設(shè)備支持USB主機(jī)模式和從機(jī)模式的支持方式只是軟支持,另外還須有硬件支持付魔,并且硬件對兩種模式的支持具有決定性。

2:Android USB Host Mode(USB 主機(jī)模式)

????????? 在Android USB Host Mode模式下飞蹂,Android設(shè)備充當(dāng)主機(jī)几苍,設(shè)備包括數(shù)碼相機(jī)、鍵盤陈哑、鼠標(biāo)和游戲控制器等妻坝。針對各類應(yīng)用和環(huán)境設(shè)計的USB設(shè)備仍可與能夠與設(shè)備正常通信的Android應(yīng)用互動。

Android USB主機(jī)模式原理圖

在USB主機(jī)模式下芥颈,我們的Android設(shè)備必須支持以下條件:

????????? 1惠勒、Android系統(tǒng)版本3.1(API Level 12)及以上。在概述中我們也提到爬坑,自Android3.1(API Level 12)開始才提供Android USB Host Mode的支持。

????????? 2涂臣、Android設(shè)備須支持OTG功能盾计。我們的智能手機(jī)和相機(jī)等移動設(shè)備本身是無法像PC那樣直接充當(dāng)USB Host為總線供電的,而OTG正是為解決此類問題而生赁遗,目前主流的Android手機(jī)和平板都已添加OTG模塊署辉。在主機(jī)模式下,我們將Android設(shè)備上的USB主機(jī)模塊又稱為USB嵌入式主機(jī)(Embedded Host 簡稱 EH)岩四。EH無法像PC上的USB主機(jī)一樣哭尝,為接入總線的未識別外圍設(shè)備加載驅(qū)動程序,所以EH設(shè)備提前在系統(tǒng)中對其目標(biāo)外圍設(shè)備列表TPL(Target Peripheral List)進(jìn)行了定義剖煌,在這些外圍USB設(shè)備中大部分是HID設(shè)備(Human Interface Device材鹦,如游戲手柄)、BOMS設(shè)備(Bulk Only Mass Storage耕姊,如讀卡器桶唐、U盤)和CDC設(shè)備(Communication Device Class,USB通信設(shè)備類茉兰,如打印機(jī)尤泽、相機(jī)),其驅(qū)動程序已存在于Android平臺的系統(tǒng)中(Linux Kernel),Android設(shè)備可以直接與這些設(shè)備直接通信坯约。

???????? 3熊咽、支持AOA協(xié)議。AOA協(xié)議(Android Open Accessory Protocol闹丐,Android開發(fā)配件協(xié)議)是Google公司推出的用于實現(xiàn)Android設(shè)備與外圍設(shè)備之間進(jìn)行USB通信的協(xié)議横殴,該協(xié)議拓展了Android設(shè)備USB接口的功能,為基于Android系統(tǒng)的智能設(shè)備應(yīng)用于設(shè)備控制和數(shù)據(jù)采集領(lǐng)域提供了條件妇智。關(guān)于AOA協(xié)議的固件源碼燒寫于硬件中滥玷,我們有時也把這項稱作為Android設(shè)備的硬件支持。(該條件僅在接入Android設(shè)備外圍設(shè)備是另一臺Android設(shè)備時需要巍棱,當(dāng)接入像U盤或打印機(jī)時惑畴,可不需要AOA協(xié)議的支持)

????????? 4、系統(tǒng)features.xml文件中提供了關(guān)于<uses-featureandroid:name="android.hardware.usb.host"/> 的定義航徙。在使用Android USB Host Mode開發(fā)時如贷,我們會在應(yīng)用程序的AndroidMainifast.xml文件中指定<uses-featureandroid:name="android.hardware.usb.host"/> 用來對不支持Android USB Host Mode的設(shè)備進(jìn)行過濾,Android系統(tǒng)版本3.1及以上默認(rèn)支持到踏,但是不排除設(shè)備商會對原生的Android系統(tǒng)進(jìn)行裁剪杠袱,可能會裁剪掉features.xml文件中關(guān)于<uses-featureandroid:name="android.hardware.usb.host"/>的定義,也就是說當(dāng)應(yīng)用程序安裝時來掃描系統(tǒng)的硬件支持feature時窝稿,發(fā)現(xiàn)沒有關(guān)于<uses-featureandroid:name="android.hardware.usb.host"/>的定義楣富,認(rèn)為該設(shè)備不支持Android USB Host Mode,也就會提示你無法安裝了伴榔。

3纹蝴、Android USB Accessory Mode(USB 從機(jī)模式)

????????? 在Android USB Accessory Mode模式下,外部USB硬件充當(dāng)USB主機(jī)踪少,配件包括機(jī)器人控制器塘安、擴(kuò)展塢、音樂設(shè)備援奢、自助服務(wù)終端兼犯、讀卡器等。不具備主機(jī)功能的Android設(shè)備就能夠與USB硬件互動集漾。Android USB配件必須設(shè)計為與Android設(shè)備兼容切黔,并且必須遵守Android配件通信協(xié)議。

Android USB從機(jī)模式原理圖

? 在USB 從機(jī)模式下帆竹,我們的Android設(shè)備必須支持以下條件:

???????? 1绕娘、Android系統(tǒng)版本2.3.4(API Level 10)及以上。在概述中我們也提到栽连,自Android3.1(API Level 12)開始才直接提供對Android USB Accessory Mode的支持险领,同時Google提供的配件開發(fā)工具包ADK(Accessory Development Kit)提供了Android設(shè)備與Android配件通過USB通信的API侨舆,該ADK包能夠向后兼容至Android2.3.4系統(tǒng)版本。(Android 3.1及以上的系統(tǒng)之所以能夠直接支持也是因為系統(tǒng)直接封裝了ADK的API)

???????? 2绢陌、必須支持AOA協(xié)議挨下。在Android USB Accessory Mode中,Android設(shè)備必須支持AOA協(xié)議脐湾,因為當(dāng)Android設(shè)備以從機(jī)的方式接入Android配件時臭笆,Android配件會通過AOA協(xié)議檢測并初始化Android設(shè)備的USB通信的環(huán)境和啟動Android設(shè)備的USB從機(jī)模式。

???????? 3秤掌、系統(tǒng)features.xml文件中提供了關(guān)于<uses-featureandroid:name="android.hardware.usb.accessory"/> 的定義愁铺。關(guān)于該條件與Android USB Host Mode中的原因一致,這里不再贅述闻鉴。

4:Android USB Host Mode 通信開發(fā)指南:


4-1:USB設(shè)備管理器在不同版本系統(tǒng)中的獲取方式不同:

Android 2.3.4版本:UsbManager manager=UsbManager.getInstance(this);
Android 3.1版本:UsbManager manager=(UsbManager)getSystemService(Context.USB_SERVICE);

4-2:配置AndroidManifest.xml:

1).添加<uses-feature>元素來聲明您的應(yīng)用使用android.hardware.usb.host功能茵乱;

2).將應(yīng)用的最低SDK設(shè)置為API級別 12 或更高級別。USB主機(jī)API在更早的API級別中不存在孟岛。

3).如果您希望應(yīng)用接收有關(guān)連接的 USB 設(shè)備的通知瓶竭,請為主 Activity 中的 android.hardware.usb.action.USB_DEVICE_ATTACHED Intent 指定 <intent-filter> 和 <meta-data> 元素對。<meta-data> 元素指向外部 XML 資源文件渠羞,用于聲明有關(guān)要檢測的設(shè)備的標(biāo)識信息斤贰。在 XML 資源文件中,為要過濾的 USB 設(shè)備聲明 <usb-device> 元素次询。下表介紹了 <usb-device> 的屬性荧恍。一般來說,如果您想過濾某個特定設(shè)備屯吊,請使用供應(yīng)商 ID 和產(chǎn)品 ID块饺;如果您想過濾一組 USB 設(shè)備(例如大容量存儲設(shè)備或數(shù)碼相機(jī)),請使用類雌芽、子類和協(xié)議。您可以指定所有這些屬性辨嗽,也可以不指定任何屬性世落。如果不指定任何屬性,則會與每個 USB 設(shè)備進(jìn)行匹配糟需,因此只在應(yīng)用需要時才這樣做:vendor-id屉佳、product-id、class洲押、subclass武花、protocol(設(shè)備或接口)如下圖:

AndroidManifest資源文件
在 res/xml/device_filter.xml 中,并指定應(yīng)過濾具有指定屬性的所有 USB 設(shè)備:


4-3:USB通信實現(xiàn)代碼封裝到UsbHidHelper類中:

?

/**

* Created by 631934797 on 2021/3/3

*/

public class UsbHidHelper {

private static final StringTAG = UsbHidHelper.class.getCanonicalName();

? ? private UsbManagermUsbManager;

? ? private UsbDeviceConnectionmUsbDeviceConnection;

? ? private UsbEndpointmUsbEndpointOut;

? ? private UsbEndpointmUsbEndpointIn;

? ? private UsbInterfacemUsbInterface;

? ? private static UsbHidHelpermInstance =null;

? ? private static ContextmContext;

? ? private boolean mToggle =true;

? ? private boolean isConnect =false;

? ? private ExecutorServicemThreadPool;

? ? private byte[]recvBuffer? =new byte[1024];

? ? private int mVendorID ;

? ? private int mProductID ;

? ? private int mFindCont =3;

? ? private final StringUSB_PERMISSION ="roy-lee.usb.permission";

? ? private PendingIntentmPrtPermissionIntent; //獲取外設(shè)權(quán)限的意圖

? ? /**

? ? * 獲取UsbHidHelper對象

? ? * @param context

? ? * @return

? ? */

? ? public static UsbHidHelper? getInstance(Context context) {

???????????? if(mInstance ==null) {

??????????? mInstance =new UsbHidHelper();

? ? ? ? ?? }

????? ?? mContext = context;

? ? ? ? return mInstance;

? ? }

/**

? ? * 初始化 USB設(shè)備

? ? *

? ? * @param vendorID

? ? * @param productID

? ? */

? ? public void initUsb_Hid(int vendorID, int productID){

??????? mVendorID = vendorID;

? ? ? ? mProductID = productID;

? ? ? ? // init UsbManager

? ? ? ? mUsbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);

? ? ? ? // 初始化線程池

? ? ? ? mThreadPool = Executors.newFixedThreadPool(5);

? ? ? ? // 注冊usb廣播

? ? ? ? registerReceiver();

? ? ? ? // 查找USB設(shè)備

? ? ? ? findUsbDevice();

? ? }

/**

? ? * 動態(tài)注冊usb廣播杈帐,拔插動作体箕,注冊動作

? ? * */

? ? private void registerReceiver(){

??????? //注冊在此service下的receiver的監(jiān)聽的action

? ? ? ? IntentFilter intentFilter =new IntentFilter();

? ? ? ? intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);

? ? ? ? intentFilter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);

? ? ? ? intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);

? ? ? ? intentFilter.addAction(USB_PERMISSION);

? ? ? ? mContext.registerReceiver(usbReceiver, intentFilter);//注冊receiver

? ? ? ? //通知監(jiān)聽外設(shè)權(quán)限注冊狀態(tài)

? ? ? ? //PendingIntent:連接外設(shè)的intent

?????? //ask permission

? ? ? ? mPrtPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(USB_PERMISSION), 0);

? ? }

private BroadcastReceiverusbReceiver =new BroadcastReceiver() {

??????? @Override

? ? ? ? public void onReceive(Context context, Intent intent) {

???????????????? if (intent ==null) {

????????????????????????? return;

? ? ? ? ? ? ? ??? }

??????????????? String action = intent.getAction();

? ? ? ? ? ? ? ? switch (action){

?????????????????????? // USB注冊動作

? ? ? ? ? ? ? ??????? case USB_PERMISSION:

????????????????????????????? synchronized (this) {

??????????????????????????????????????? if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {

UsbDevice parcelableExtra = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (parcelableExtra !=null) {

// 連接設(shè)備

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? connectDevice(parcelableExtra);

? ? ? ? ? ? ? ? ? ? ? ? ? ? }else {

Log.e(TAG,"usb device suddenly disappera.");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG,"...USB外設(shè)意外消失...");

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

}else {

Log.e(TAG,"usb permission granted fail.");

? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG,"...USB權(quán)限注冊失敗...");

? ? ? ? ? ? ? ? ? ? ? ? ? ? mFindCont--;

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (mFindCont >0){

findUsbDevice();

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

}

}

break;

? ? ? ? ? ? ? ? // USB插入動作

? ? ? ? ? ? ? ? case UsbManager.ACTION_USB_ACCESSORY_ATTACHED:

case UsbManager.ACTION_USB_DEVICE_ATTACHED:

Log.i(TAG,"...USB 插入...");

? ? ? ? ? ? ? ? ? ? mFindCont =3;

? ? ? ? ? ? ? ? ? ? findUsbDevice();

break;

? ? ? ? ? ? ? ? // USB拔出動作

? ? ? ? ? ? ? ? case UsbManager.ACTION_USB_DEVICE_DETACHED:

Log.e(TAG,"...USB 已被拔出...");

? ? ? ? ? ? ? ? ? ? mToggle =true;

? ? ? ? ? ? ? ? ? ? isConnect =false;

break;

? ? ? ? ? ? }

}

};

? ? /**

? ? *? 查找設(shè)備

? ? */

? ? private boolean findUsbDevice(){

mThreadPool.execute(new Runnable() {

@Override

? ? ? ? ? ? public void run() {

//? ? ? ? ? ? ? ? while (mToggle && mFindCont > 0) {

? ? ? ? ? ? ? ? ? ? Log.d(TAG, "...查找USB設(shè)備...");

? ? ? ? ? ? ? ? ? ? HashMap deviceList =mUsbManager.getDeviceList();

? ? ? ? ? ? ? ? ? ? Collection values = deviceList.values();

? ? ? ? ? ? ? ? ? ? if (!values.isEmpty()) {

for (UsbDevice usbDevice : values) {

// 輸出設(shè)備信息

? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG,"mVendorID : "+mVendorID +"? mProductID : " +mProductID);

? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.d(TAG, "設(shè)備ID: vid = " + String.format("%x", usbDevice.getVendorId()) +" , pid = " + String.format("%x", usbDevice.getProductId()));

? ? ? ? ? ? ? ? ? ? ? ? ? ? int vendorId = usbDevice.getVendorId();

? ? ? ? ? ? ? ? ? ? ? ? ? ? int productId = usbDevice.getProductId();

? ? ? ? ? ? ? ? ? ? ? ? ? ? if (vendorId ==mVendorID && productId ==mProductID) {

Log.d(TAG, "...枚舉SUB設(shè)備成功...");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 獲取權(quán)限

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (mUsbManager.hasPermission(usbDevice)) {

// 建立連接

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? connectDevice(usbDevice);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else {

Log.e(TAG,"...申請USB權(quán)限失敗...");

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mUsbManager.requestPermission(usbDevice, mPrtPermissionIntent);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }

}

}

}else {

// TODO 沒有USB設(shè)備

? ? ? ? ? ? ? ? ? ? ? ? Log.e(TAG,"...沒有USB設(shè)備...");

? ? ? ? ? ? ? ? ? ? }

//? ? ? ? ? ? ? ? ? ? SystemClock.sleep(10000);

//? ? ? ? ? ? ? ? ? ? mFindCont--;

//? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

});

? ? ? ? return isConnect;

? ? }

/**

? ? * 連接設(shè)備

? ? * @param usbDevice

? ? */

? ? private void connectDevice(UsbDevice usbDevice){

Log.e(TAG,"...申請USB權(quán)限成功...");

? ? ? ? Log.e(TAG,"UsbDevice :" + usbDevice);

? ? ? ? // 打開設(shè)備

? ? ? ? UsbDeviceConnection conn=mUsbManager.openDevice(usbDevice);

? ? ? ? if (conn !=null) {

mUsbInterface = usbDevice.getInterface(0);

? ? ? ? ? ? if (conn.claimInterface(mUsbInterface, true)){

mUsbDeviceConnection = conn;

? ? ? ? ? ? ? ? int endpointCount =mUsbInterface.getEndpointCount();

? ? ? ? ? ? ? ? for (int i =0; i < endpointCount; i++) {

UsbEndpoint usbEndpoint =mUsbInterface.getEndpoint(i);

? ? ? ? ? ? ? ? ? ? Log.e(TAG,"Type: "+ usbEndpoint.getType());

? ? ? ? ? ? ? ? ? ? Log.e(TAG,"Direction: "+ usbEndpoint.getDirection());

? ? ? ? ? ? ? ? ? ? // TODO USB 4種傳輸模式专钉,根據(jù)自己實際通信需求自行更改

? ? ? ? ? ? ? ? ? ? if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_INT) {

if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {

mUsbEndpointOut = usbEndpoint;

? ? ? ? ? ? ? ? ? ? ? ? }else if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {

mUsbEndpointIn = usbEndpoint;

? ? ? ? ? ? ? ? ? ? ? ? }

}

}

if (mUsbEndpointOut !=null &&mUsbEndpointIn !=null) {

// TODO 連接USB設(shè)置成功

? ? ? ? ? ? ? ? ? ? Log.i(TAG,"connected success");

? ? ? ? ? ? ? ? ? ? mToggle =false;

? ? ? ? ? ? ? ? ? ? isConnect =true;

? ? ? ? ? ? ? ? ? ? onLoopSendData();

? ? ? ? ? ? ? ? }

}

}

}

/**

? ? * 發(fā)送HID數(shù)據(jù)

? ? *

? ? * @param messageContent

? ? * @return

? ? */

? ? public boolean sendHidData(String messageContent){

return sendHidData(messageContent.getBytes());

? ? }

public boolean sendHidData(final byte[] contentBytes){

final boolean[] states = {false};

? ? ? ? mThreadPool.execute(new Runnable() {

@Override

? ? ? ? ? ? public void run() {

if (mUsbDeviceConnection !=null &&mUsbEndpointOut !=null) {

/**

? ? ? ? ? ? ? ? ? ? * 發(fā)送數(shù)據(jù)的地方 , 只接受byte數(shù)據(jù)類型的數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? */

? ? ? ? ? ? ? ? ? ? int i =mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, contentBytes, contentBytes.length, 2000);

? ? ? ? ? ? ? ? ? ? if (i >0) {

Log.i(TAG,"發(fā) ==> ◇: " + HexDump.byteTo16String(contentBytes) +"\r\n");

? ? ? ? ? ? ? ? ? ? ? ? states[0] =true;

? ? ? ? ? ? ? ? ? ? }else {

Log.e(TAG,"...數(shù)據(jù)發(fā)送失敗...");

? ? ? ? ? ? ? ? ? ? }

}else {

Log.e(TAG,"...請先連接USB...");

? ? ? ? ? ? ? ? }

}

});

? ? ? ? return states[0];

? ? }

/**

? ? * 接收HID數(shù)據(jù)

? ? *

? ? * @param callback

? ? */

? ? public void receivedHidNewData(final HidDataCallback callback){

mThreadPool.execute(new Runnable() {

@Override

? ? ? ? ? ? public void run() {

while (true) {

/**

? ? ? ? ? ? ? ? ? ? * 循環(huán)接受數(shù)據(jù)的地方 , 只接受byte數(shù)據(jù)類型的數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? */

? ? ? ? ? ? ? ? ? ? if (mUsbDeviceConnection !=null &&mUsbEndpointIn !=null &&isConnect) {

int i =mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, recvBuffer, 64, 1000);

? ? ? ? ? ? ? ? ? ? ? ? if (i >0) {

byte[] subArray = HexDump.getSubArray(recvBuffer, 0, i);

? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.i(TAG,"收 <== ◆: "+HexDump.byteTo16String(subArray) +"\r\n");

? ? ? ? ? ? ? ? ? ? ? ? ? ? if(callback !=null)

callback.onReceiveHidData(subArray);

? ? ? ? ? ? ? ? ? ? ? ? }

}

SystemClock.sleep(10);

? ? ? ? ? ? ? ? }

}

});

? ? }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者累铅。
  • 序言:七十年代末跃须,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子娃兽,更是在濱河造成了極大的恐慌菇民,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件投储,死亡現(xiàn)場離奇詭異第练,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)玛荞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門娇掏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冲泥,你說我怎么就攤上這事驹碍。” “怎么了凡恍?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵志秃,是天一觀的道長。 經(jīng)常有香客問我嚼酝,道長浮还,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任闽巩,我火速辦了婚禮钧舌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涎跨。我一直安慰自己洼冻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布隅很。 她就那樣靜靜地躺著撞牢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叔营。 梳的紋絲不亂的頭發(fā)上屋彪,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音绒尊,去河邊找鬼畜挥。 笑死,一個胖子當(dāng)著我的面吹牛婴谱,可吹牛的內(nèi)容都是我干的蟹但。 我是一名探鬼主播躯泰,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矮湘!你這毒婦竟也來了斟冕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缅阳,失蹤者是張志新(化名)和其女友劉穎磕蛇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體十办,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秀撇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了向族。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呵燕。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖件相,靈堂內(nèi)的尸體忽然破棺而出再扭,到底是詐尸還是另有隱情,我是刑警寧澤夜矗,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布泛范,位于F島的核電站,受9級特大地震影響紊撕,放射性物質(zhì)發(fā)生泄漏罢荡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一对扶、第九天 我趴在偏房一處隱蔽的房頂上張望区赵。 院中可真熱鬧,春花似錦浪南、人聲如沸笼才。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽患整。三九已至,卻和暖如春喷众,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背紧憾。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工到千, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赴穗。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓憔四,卻偏偏與公主長得像膀息,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子了赵,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • USB模式 支持USB accessory模式和USB host模式潜支。通過這兩種模式,android支持各種各樣的...
    yqyzxd閱讀 22,774評論 7 18
  • USB相關(guān)概念: 簡單來說柿汛,USB 是一個用于數(shù)據(jù)交換的總線(Bus)冗酿。發(fā)啟(initiate)數(shù)據(jù)交換的一方稱為...
    Tifkingsly閱讀 9,294評論 2 8
  • 原文地址:https://blog.csdn.net/VNanyesheshou/article/details/...
    皮子熙閱讀 7,206評論 0 2
  • USB OTG: USB On-The-Go的簡稱,是USB 2.0規(guī)定的補(bǔ)充標(biāo)準(zhǔn)络断,它可以使手機(jī)等作為USB主機(jī)裁替,...
    衣谷文武閱讀 5,202評論 0 1
  • Android音頻系統(tǒng)詳解 參考好文: Android 音頻系統(tǒng):從 AudioTrack 到 AudioFlin...
    愛雨520閱讀 13,646評論 2 7