編輯:關於Android編程
Android中的WiFi P2P能夠允許一定范圍內的設備通過Wifi直接互連而不必通過熱點或互聯網。
使用WiFi P2P需要Android API Level >= 14才可以,而且不要忘記在Manifest文件中加入下面5個權限:
● android.permission.ACCESS_WIFI_STATE
● android.permission.CHANGE_WIFI_STATE
● android.permission.ACCESS_NETWORK_STATE
● android.permission.CHANGE_NETWORK_STATE
● android.permission.INTERNET (WiFi P2P並不需要連接互聯網,但是因為要用到Java Socket,所以要加這個權限)
關於WiFi P2P的操作幾乎都靠WifiP2pManager來進行,所以如果你的程序要用到WiFi P2P功能,可以設置一個全局變量wifiP2pManager,然後在onCreate()生命函數中獲取系統WifiP2pManager對象:
wifiP2pManager = (WifiP2pManager) getApplicationContext().getSystemService(Context.WIFI_P2P_SERVICE);
initialize()
在使用WiFi P2P功能時必須先調用這個方法,用來通過WiFi P2P框架注冊我們的應用
connect()
根據配置(WifiP2pConfig對象)與指定設備(WifiP2pDevice對象)進行P2P連接
cancelConnect()
關閉某個P2P連接
requestConnectInfo()
獲取設備的連接信息
createGroup()
以當前的設備為組長創建P2P小組
removeGroup()
移除當前的P2P小組
requestGroupInfo()
獲取P2P小組的信息
discoverPeers()
初始化peers發現操作
requestPeers()
獲取當前的peers列表(通過discoverPeers發現來的)
每當WifiP2pManager執行某個P2P操作時,可以通過不同的監聽器來檢測這些操作的反饋結果,這些監聽器的類型如下:
WifiP2pManager.ActionListener
connect()
, cancelConnect()
, createGroup()
, removeGroup()
和discoverPeers()
WifiP2pManager.ChannelListener
initialize()
WifiP2pManager.ConnectionInfoListener
requestConnectInfo()
WifiP2pManager.GroupInfoListener
requestGroupInfo()
WifiP2pManager.PeerListListener
requestPeers()
那麼接下來就可以講解如何使用WiFi P2P了。
一. 准備工作
准備階段需要讓我們的應用可以接受P2P信號,這就需要一個意圖廣播接收器,要創建一個符合我們要求的廣播接收器需要准備下面3個要素:
(1) 一個意圖廣播接收器,用來接受意圖廣播。
(2) 通過WifiP2pManager的initialize()初始化操作來獲取一個Channel對象,用於以後和WiFi P2P框架保持通信。
(3) 自己包裝BroadcastReceiver類,實現一個接收器。
意圖過濾器使用如下方法創建:
// 設置intent過濾器 intentFilter = new IntentFilter(); //一個全局的intentFilter對象 intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); // WiFi P2P是否可用 intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); // peers列表發生變化 intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); // WiFi P2P連接發生變化 intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); // WiFi P2P設備信息發生變化(比如更改了設備名)
channel = wifiP2pManager.initialize(getApplicationContext(), getMainLooper(), null); // channel是一個全局的Channel對象
意圖廣播接收器的創建需要通過繼承BroadcastReceiver類來自己實現,下面給出了一段示例:
class MyBroadcastReceiver extends BroadcastReceiver { // 使用WiFi P2P時,自己定義的BroadcastReceiver的構造函數一定要包含下面這三個要素 private WifiP2pManager wifiP2pManager; private Channel channel; private Activity activity; public MyBroadcastReceiver(WifiP2pManager wifiP2pManager, Channel channel, Activity activity) { this.wifiP2pManager = wifiP2pManager; this.channel = channel; this.activity = activity; } // onReceiver對相應的intent進行處理 @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) { int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1); if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { // WiFi P2P 可以使用 } else { // WiFi P2P 不可以使用 } } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) { } } }
定義完了之後就可以再需要的地方實例化一個意圖廣播接收器對象了:
broadcastReceiver = new MyBroadcastReceiver(wifiP2pManager, channel, this);
那麼三個要素都具備了之後就要向應用注冊我們的接收器,好讓它可以開始工作:
registerReceiver(broadcastReceiver, intentFilter);
二. 啟動peers發現
public void discoverPeers(View view) { peerListListener = new WifiP2pManager.PeerListListener() { @Override public void onPeersAvailable(WifiP2pDeviceList peerList) { peers.clear(); // peers是一個全局ArrayList對象,用於保存發現的peers的信息 peers.addAll(peerList.getDeviceList()); // 如果你有一個控件用來顯示這些peers的信息,就可以再這裡更新了 } }; wifiP2pManager.discoverPeers(channel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { Toast.makeText(getApplicationContext(), "discover peers!", Toast.LENGTH_SHORT); } @Override public void onFailure(int arg0) { } }); // discoverPeers是異步執行的,調用了之後會立刻返回,但是發現的過程一直在進行, // 直到發現了某個設備時就會通知你 }
當發現了設備之後就會觸發WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION意圖廣播,你可以再之前自己包裝的BroadcastReceiver類中加入對這一意圖的處理:
else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) { if (wifiP2pManager != null) { wifiP2pManager.requestPeers(channel, peerListListener); } }
三. 與peers建立連接
public void connect() { final WifiP2pDevice device = (WifiP2pDevice) peers.get(0); //從peers列表中獲取發現來的第一個設備 WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = device.deviceAddress; config.wps.setup = WpsInfo.PBC; wifiP2pManager.connect(channel, config, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // 連接成功 Toast.makeText(getApplicationContext(), "與設備" + device.deviceName + "連接成功", Toast.LENGTH_LONG).show(); } @Override public void onFailure(int arg0) { // 連接失敗 Toast.makeText(getApplicationContext(), "與設備" + device.deviceName + "連接失敗", Toast.LENGTH_LONG).show(); } }); }
每當有P2P連接狀態發生改變時,就會觸發WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION意圖廣播,可以在之前你自己包裝的BroadcastReceiver類中加入對這一意圖的處理:
else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) { if (wifiP2pManager == null) return; NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); if (networkInfo.isConnected()) { // We are connected with the other device, request // connection // info to find group owner IP wifiP2pManager.requestConnectionInfo(channel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { // 這裡可以查看變化後的網絡信息 // 通過傳遞進來的WifiP2pInfo參數獲取變化後的地址信息 InetAddress groupOwnerAddress = info.groupOwnerAddress; // 通過協商,決定一個小組的組長 if (info.groupFormed && info.isGroupOwner) { // 這裡執行P2P小組組長的任務。 // 通常是創建一個服務線程來監聽客戶端的請求 } else if (info.groupFormed) { // 這裡執行普通組員的任務 // 通常是創建一個客戶端向組長的服務器發送請求 } } }); } }
Android中Button控件應該算作是比較簡單的控件,然而,它的使用頻率卻是非常的高,今天,我在這裡總結了三種常用的點擊Button實現其功能的方法。1.很多時候,我
說到圖像處理,第一件事就是要從手機相冊選擇圖片,然後才是處理。其實,用代碼實現從手機相冊選擇一張圖片其實非常簡單:添加一個Button,id設為btnOpen;對該But
--------------------------------------廣播機制簡介-----------------------------------------
由於我們使用的國行版手機沒有內置谷歌服務框架,在使用過程中如果安裝谷歌地圖(Google Map)和谷歌商城(Google Play)之類的官方應用時就會閃