USB上網卡分無線3G和有線,無線3G上網卡我的同事已經實現,我最近實現的是有線。即通過RJ45轉USB串連到MID,驅動會註冊好ethX的網路裝置,我要實現的就是操作該網路裝置就可以了。
ConnectivityService是管理已連線的服務,它管理多個網路類型Tracker,如WifiStateTracker,MobileDataStateTracker,類似的,我需要實現UsbNetworkStateTracker。
ConnectivityService在執行個體化某個Tracker時,會傳遞進去一個Handler的回調,如果某個Tracker發生狀態改變(訊號強度,串連狀態等),都會通過給該回調發送訊息,ConnectivityService根據狀態變化,嚮應用層發送intent。一個典型的例子是資料連線成功後的動作:
private void sendConnectedBroadcast(NetworkInfo info) {<br /> Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);<br /> intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);<br /> intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);<br /> if (info.isFailover()) {<br /> intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);<br /> info.setFailover(false);<br /> }<br /> if (info.getReason() != null) {<br /> intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());<br /> }<br /> if (info.getExtraInfo() != null) {<br /> intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,<br /> info.getExtraInfo());<br /> }<br /> sendStickyBroadcast(intent);<br /> }<br />
各類Tracker都是繼承自NetworkStateTracker,而NetworkStateTracker繼承自Handler,NetworkStateTracker有一個的NetworkInfo執行個體,儲存當前網路類型的狀態,應用程式可以通過ConnectivityService用戶端ConnectivityManager的getAllNetworkInfo()來獲得這些執行個體。
UsbNetworkStateTracker跟WifiStateTracker不一樣的地方是,WIFI有自己的服務,應用程式可以調用WifiService的用戶端WifiManager來操縱wifi裝置,從而調用到WfiStateTracker,我只能通過自定的訊息來操作UsbNetworkStateTracker,
自訂的兩個動作包括:
public static final String ACTION_USB_NETWORK_START = "android.net.usb.NETWORK_START";<br />public static final String ACTION_USB_NETWORK_STOP = "android.net.usb.NETWORK_STOP";<br />
應用程式發送包含該動作的intent,UsbNetworkStateTracker收到以後會執行相應的動作。
除此之外,UsbNetworkStateTracker還應該能識別當前可用的網路裝置的名稱,NetworkManagementService提供了一個介面INetworkManagementEventObserver,只要繼承這個介面裡面的三個回調的方法,
interface INetworkManagementEventObserver {<br /> /**<br /> * Interface link status has changed.<br /> *<br /> * @param iface The interface.<br /> * @param link True if link is up.<br /> */<br /> void interfaceLinkStatusChanged(String iface, boolean link);<br /> /**<br /> * An interface has been added to the system<br /> *<br /> * @param iface The interface.<br /> */<br /> void interfaceAdded(String iface);<br /> /**<br /> * An interface has been removed from the system<br /> *<br /> * @param iface The interface.<br /> */<br /> void interfaceRemoved(String iface);<br />}<br />
然後通過下面代碼註冊這個介面
// register for notifications from NetworkManagement Service<br /> IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);<br /> INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);<br /> try {<br /> service.registerObserver(mInterfaceObserver);<br /> } catch (RemoteException e) {<br /> Log.e(TAG, "Error registering observer :" + e);<br /> }<br />
這樣你的Tracker就能監聽到網路裝置的插拔了,這樣做是為了保持與wifi的相容,否則你不知道eth0 和eth1對應的wifi還是usb網卡。
UsbNetworkStateTracker通過調用NetworkUtils的方法來操縱網路裝置。典型的方法是執行DHCP,通過調用
public native static boolean runDhcp(String interfaceName, DhcpInfo ipInfo);
這個通過jni調用到dhcpclient.c裡面的函數。
如果說不加Tracker行不行,在apk裡面直接調用NetworkUtils是沒有許可權的,就算是獲得了所有的網路許可權,甚至在AndroidManifest裡面將android:sharedUserId設定為android.uid.system都不行,原因我到現在還沒搞清楚。其實實現一個Tracker也還好,不用自己去管理一些中間狀態,而且對應用程式層很友好。
加了一個Tracker會改變android的api,可能會遇到編譯上的問題,你需要到工程目錄下(比如/all/froyo/)
運行如下命令:make update-api; make PRODUCT-sdk-sdk;
具體參考:http://hi.baidu.com/programmar/blog/item/732776ea307360dfd439c938.html