天天看點

Android USB下的Accessory模式

Android USB開發麻煩還是比較多的。

第一種:host模式

Android USB下的Accessory模式

這種模式比較不錯,由Android裝置提供電源,然後與外部裝置通信。舉個例子來說:電腦連接配接USB裝置,都是這個模式,非常常見的模式。

但是有一個萬惡的問題,android接外部USB裝置的時候,驅動怎麼辦?又有那款晶片敢說Android系統支援他們家的晶片,又有哪個廠家說不動android系統裝上他們家的驅動,他們家的裝置就可以在Android上使用,或許這點上Android很難超越windows。

造成想現狀:想加外部裝置,都要:重新自己做底層驅動程式--->編譯系統--->刷機--->編寫android程式--->接入硬體實作功能。

整個一套下來飯都吃好幾頓了。還是希望以後android發展發展能向window一樣支援多裝置驅動吧。

第二種:Accessory模式

Android USB下的Accessory模式

這個模式比較揪心,外部裝置要供給電源,資料間通信:電腦---手機就是這種模式,手機作為Accessory裝置,電腦供給它電源,同時進行資料通信。

恰巧我也是用了這種模式:

程式需要做的:

(1)添加Action BoardCast

private static final String ACTION_USB_PERMISSION ="com.ukey.USB_PERMISSION";

/***********************USB handling******************************************/
		usbmanager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
		mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
		IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
		
		filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);		
		context.registerReceiver(mUsbReceiver, filter);
		inputstream = null;
		outputstream = null;
           

(2)編寫對應的boradCaset資訊

/***********USB broadcast receiver*******************************************/
	private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() 
	{
		@Override
		public void onReceive(Context context, Intent intent) 
		{
			String action = intent.getAction();
			if (ACTION_USB_PERMISSION.equals(action)) 
			{
				synchronized (this)
				{
					UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
					if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false))
					{
						Toast.makeText(global_context, "Allow USB Permission", Toast.LENGTH_SHORT).show();
						OpenAccessory(accessory);	
						
					}else{
						Toast.makeText(global_context, "Deny USB Permission", Toast.LENGTH_SHORT).show();
					}
					mPermissionRequestPending = false;
				}
			} 
			else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)){
				DestroyAccessory(true);
			}else{
				Log.d("LED", "....");
			}
		}
	};
           

(3)又來一個比較麻煩的事

android每次使用Accessory的時候都會詢問你是否允許裝置通路,這會點選是或否的結果又(2)中代碼

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

去獲得,然後才能使用OpenAccessory功能。

public int OpenAccessory()
	{
		// Intent intent = getIntent();
		if (inputstream != null && outputstream != null) {
			return 1;
		}
		UsbAccessory[] accessories = usbmanager.getAccessoryList();
		if(accessories != null){
			Toast.makeText(global_context, "Accessory Attached", Toast.LENGTH_SHORT).show();
		}else{
			// return 2 for accessory detached case
			return 2;
		}
		UsbAccessory accessory = (accessories == null ? null : accessories[0]);
		if (accessory != null) {
			if( -1 == accessory.toString().indexOf(ManufacturerString)){
				Toast.makeText(global_context, "Manufacturer is not matched!", Toast.LENGTH_SHORT).show();
				return 1;
			}
			if( -1 == accessory.toString().indexOf(ModelString1) && -1 == accessory.toString().indexOf(ModelString2))
			{
				Toast.makeText(global_context, "Model is not matched!", Toast.LENGTH_SHORT).show();
				return 1;
			}if( -1 == accessory.toString().indexOf(VersionString))
			{
				Toast.makeText(global_context, "Version is not matched!", Toast.LENGTH_SHORT).show();
				return 1;
			}
			Toast.makeText(global_context, "Manufacturer, Model & Version are matched!", Toast.LENGTH_SHORT).show();
			if (usbmanager.hasPermission(accessory)) {
				OpenAccessory(accessory);
			}else{
				synchronized (mUsbReceiver) {
					if (!mPermissionRequestPending) {
						Toast.makeText(global_context, "Request USB Permission", Toast.LENGTH_SHORT).show();
						usbmanager.requestPermission(accessory,mPermissionIntent);
						mPermissionRequestPending = true;
					}
				}
			}
		}
		return 0;
	}
           

啟動請求。

(4)openAccessory功能

/*destroy accessory*/
	public void DestroyAccessory(boolean bConfiged){

		if(true == bConfiged){
			READ_ENABLE = false;  // set false condition for handler_thread to exit waiting data loop
			writeusbdata[0] = 0;  // send dummy data for instream.read going
			SendPacket(1, writeusbdata);
		}else{
			SetConfig((int)9600,(byte)8,(byte)1,(byte)0,(byte)0);  // send default setting data for config
			try{Thread.sleep(10);}
			catch(Exception e){}

			READ_ENABLE = false;  // set false condition for handler_thread to exit waiting data loop
			writeusbdata[0] = 0;  // send dummy data for instream.read going
			SendPacket(1, writeusbdata);
		}
		try{Thread.sleep(10);}
		catch(Exception e){}			
		CloseAccessory();
	}

	/*********************helper routines*************************************************/		

	public void OpenAccessory(UsbAccessory accessory)
	{
		filedescriptor = usbmanager.openAccessory(accessory);
		if(filedescriptor != null){
			usbaccessory = accessory;
			FileDescriptor fd = filedescriptor.getFileDescriptor();
			inputstream = new FileInputStream(fd);
			outputstream = new FileOutputStream(fd);
			/*check if any of them are null*/
			if(inputstream == null || outputstream==null){
				return;
			}
			if(READ_ENABLE == false){
				READ_ENABLE = true;
				readThread = new read_thread(inputstream);
				readThread.start();
			}
		}
		SetConfig((int)9600,(byte)8,(byte)1,(byte)0,(byte)0);
	}

	public void CloseAccessory()
	{
		try{
			if(filedescriptor != null)
				filedescriptor.close();
		}catch (IOException e){}

		try {
			if(inputstream != null)
				inputstream.close();
		} catch(IOException e){}

		try {
			if(outputstream != null)
				outputstream.close();

		}catch(IOException e){}
		/*FIXME, add the notfication also to close the application*/

		filedescriptor = null;
		inputstream = null;
		outputstream = null;
		//System.exit(0);
	}