Androidアプリケーション技術者認定試験ベーシックの試験範囲の知識をまとめた(8)

# 通信

## ネットワークプロトコル

- ソケットを使ったTCP/IP通信
- HTTPプロトコルを使った通信

### TCP/IP通信

インターネット標準の通信

#### Socketクラス

java.net.Socketクラスを使用して通信する
Socketクラスを使用するには以下の2つの方法がある

1. connectメソッドで指定した通信相手に接続する方法

  Socketクラスを生成し、connectメソッドに接続先IPとポートを渡して接続する。
  (InetSocketAddressクラスのインスタンス)

1. コンストラクタで通信相手を指定する方法

  Socketクラスを生成する際に、アドレスと、ポートを渡して接続する。

TCP/IP通信通信をするにはマニフェストファイルにandroid.permission.INTERNETを指定して
権限をもらう必要がある。

#### InputStreamクラス

データを受信するにはInputStreamクラスを用いる。
SocketクラスのgetInputStreamメソッドでInputStreamクラスのインスタンスを取得する。
得られたインスタンスのreadメソッドを利用して、byte配列に受信できる。

#### OutputStreamクラス

データを送信するにはOutputStreamクラスを用いる。
SocketクラスのgetOutputStreamメソッドでOutputStreamクラスのインスタンスを取得する。
得られたインスタンスのwriteメソッドを利用して、byte配列を送信できる。
最後にflushメソッドを使うことで、送信実施できる。

### HTTP通信

以下の3つのクラスがある。

- org.apache.http.impl.client.DefaultHttpClient
- android.net.http.AndroidHttpClient
- java.net.HttpURLConnection

#### DefaultHttpClientクラス

org.apache.http.client.methodsのHttpGetクラスのインスタンスを生成する。引数としてリクエストしたいURLを渡しておく。
次にDefaultHttpClientのインスタンスを生成し、executeメソッドにっ最初に作ったHttpGetクラスのインスタンスを渡す。
レスポンスとして、HttpResponseクラスのインスタンスが返ってくる。
返ってきたHttpResponseクラスのインスタンスを利用して、リクエストに対する結果を判定できる。

POSTリクエストを行う場合はorg.apache.http.client.methods.HttpPostクラスを使用する。

#### AndroidHttpClientクラス

Androidに最適化されたHTTP通信を行うために用意されたもの。

- UIスレッドで使うことが禁じられている
- Cookieが使用できない
- コンテンツのgzip圧縮処理が追加されている
- リダイレクトが禁止されている
- Android2.2(APIレベル8)以降で導入されたクラス

AsyncTaskを使用するのが一般的

AndroidHttpClientクラスのインスタンスを生成するには、引数にUserAgent名を指定してnewInstanceメソッドを呼び出す。

#### HttpURLConnectionクラス

Java標準のクラス。
接続先のURLを指定してURLクラスのインスタンスを生成する。URLクラスのopenConnectionメソッドを呼び出して、HttpURLConnectionクラスのインスタンスを取得する。setRequestMethodメソッドでリクエストで使用するメソッド(GET, POST)を指定して、connectメソッドでリクエスト送信し、レスポンス取得が可能となる。
レスポンスからは、getResponseCodeメソッドでレスポンスコードが取得できる。
またgetInputStreamメソッドでInputStreamクラスのインスタンスが取得できデータを読み取れる。
取得後は、disconnectメソッドで切断する。

##### 通信処理はメインスレッド（UIスレッド）では行わない

通信処理は時間がかかるのでUIスレッドでは実施しないこと。
5秒以上止まってしまうと、ANR（Android Not Responding）が発生してしまう場合がある。

## Bluetooth

Android2.0(APIレベル5)以降で利用可能

### Bluetoothのプロファイル

Bluetoothプロファイルとは、通信機器の種類によってプロトコルを標準化したもの

|||
|---|---|
|DUM|Bluetoothを通して、インターネットやダイヤルアップサービスにアクセスするためのプロファイル|
|HID|キーボードやマウスなどの入力デバイス用|
|HSP|ワイヤレスホンやカーナビと接続し、ハンズフリー通話するためのもの|
|OPP|電話帳などのデータ送受信するためのプロファイル|
|SPP|仮想シリアルポートを設定し、それらを接続するためのプロファイル|

### Bluetoothを有効にする

BluetoothAdapterクラスのgetDefaultAdapterメソッドを呼び出すことで、インスタンスを取得できる。
取得できない場合は端末がBluetoothをサポートしていないことを表す。
取得したインスタンスのisEnabledメソッドで有効になっているかどうかを調べることが出来る
有効にするには、ACTION_REQUEST_ENABLEをインテントのコンストラクタに指定して、インテントを生成し、
startActivityForResultメソッドを呼び出す。これによりBluetooth許可リクエストダイアログが表示される
ダイアログの結果はonActivityResultメソッドに返される。有効になった場合は、resultCodeにActivity.RESULT_OKが渡され、Bluetoothが有効にできなかった場合はActivity.RESULT_CANCELEDが渡される。

### Bluetoothデバイスを検索する

BluetoothAdapterクラスのstartDiscoveryメソッドを呼び出すことで、検索を開始できる。
検索処理は非同期で実施される。見つかるとACTION_FOUNDのインテントに見つけたデバイスの
情報を含ませてブロードキャストするため。受け取るブロードキャストレシーバが必要となる。
ブロードキャストレシーバのonReceiveメソッドを実装する。
BluetoothDevice.EXTRA_DEVICEという名前でデバイスの情報を保持するBluetoothDeviceクラスのインスタンスが格納されている。

### ペアリング済み Bluetoothデバイス一覧の取得

BluetoothAdapterクラスのgetBondedDevicesメソッドを呼び出すことで、ペアリング済みのデバイス情報のリストを取得できる

#### デバイスの接続と通信

クライアントとして特定のデバイスに接続をするためには、BluetoothDeviceクラスのインスタンスから、
BluetoothSocketクラスのインスタンスを生成し、connectメソッドによってサーバ側機器と接続する。

**UUID**(Univerally Unique Identifier: 汎用一意識別子)はプロファイルごとに決まった値を指定する必要がある。

接続後のデータは、BluetoothSocketクラスのインスタンスから、InputStreamとOutputStreamを取得して行うことが出来る。

#### リモートデバイスのデバイス検索に応答する

デバイスを他のデバイスから発見可能にしたい場合は、ACTION_REQUEST_DISCOVERABLEをインテントのコンストラクタに指定し、startActivityForResultメソッドを呼び出す。
これによりダイアログが表示され、許可することで言って時間応答できるようになる。
onActivityResultメソッドの引数resultCodeに最大応答時間の値が入っている。

##### リモートデバイスからの接続要求の受付をする

サーバ側で接続を受け付けるには、BluetoothServerSocketクラスを使用する。
BluetoothAdapterクラスのlistenUsingRfcommWithServiceRecordを呼び出すことで、BluetoothServerSocketクラスのインスタンスが取得できる。引数にはサービス名とプロファイルのUUIDを指定する。
接続要求の受付はacceptメソッドで行い、完了したらcloseメソッドで切断する。BluetoothSocketクラスの扱いと同じになる。
acceptメソッドの呼び出しは、接続受付か例外発生までブロックされるためUIスレッドとは別スレッドで実施する必要がある。

#### Bluetoothの利用許可

アプリケーションでBluetoothを操作するにはマニフェストファイルにandroid.permission.BLUETOOTHを指定する必要がある。Bluetoothの有効化/無効化やデバイス検索をするにはandroid.permission.BLUETOOTH_ADMINも必要となる。

## Wi-Fi

### Wi-Fi機能の有効化

android.net.wifiパッケージのWifiManagerクラスでWi-Fi機能を制御できる。WifiManagerクラスのsetWifiEnabledメソッドにより、Wi-Fi機能の有効／無効を切り替えることが出来る。
isWifiEnabledメソッドで、現在有効なのか無効なのかを調べることが出来る。

### Wi-Fiアクセスポイントの探索

アクセスポイントの探索をするにはWiFiManagerクラスのstartScanメソッドを使う。結果はgetScanResultsメソッドにより取得できる。

探索終了時にはSCAN_RESULTS_AVAILABLE_ACTIONを持つインテントがブロードキャストされる。そのため結果を取得するにはこのインテントを受け取るブロードキャストレシーバを作成し、onReceiveメソッドでgetScanResultsメソッドを呼び出す。List\<ScanResult>が返ってくるので取り出して使用できる。

ScanResultの内容

|||
|---|---|
|BBSID|基本サービスセット識別子|
|SSID|無線LANの識別子|
|capabilities|暗号化情報|
|frequency|チャンネル周波数|
|level|信号レベル|

### Wi-Fiアクセスポイントへの接続

接続するためにはWifiConfigurationクラスのインスタンスにSSID(Service Set Identifier: 無線LANアクセスポイント識別子)やWEP(Wired Equivalent Privacy:無線LANで使われる共通鍵暗号方式)のキーを設定して、
addNetworkメソッドを呼び出すことで行える。
戻り値として、ネットワークIDが返されるのでこの値をenableNetworkメソッドの引数に渡すことで接続を有効にできる。saveConfigurationメソッドで接続した情報をシステムに保存できる。

### Wi-Fi接続設定情報の取得

設置情報はWiFiManagerクラスのgetConfiguredNetworksメソッドで取得できる。
設定情報は複数あるのでWifiConfigurationが入ったListで返される。

Wifiの設定情報

|||
|---|---|
|BBSID|基本サービスセット識別子|
|SSID|無線LANの識別子|
|allowedAuthAlgorithms|サポートされる認証プロトコル|
|allowedGroupCiphers|サポートされているGroup Cipher|
|allowedKeyManagement|サポートされているキー管理|
|allowedPairwiseCiphers|サポートされているPairwise Cipher|
|allowedProtocols|サポートされているセキュリティプロトコル|
|hiddenSSID|ステルスモードを示すフラグ|
|networkId|ネットワーク番号|
|preSharedKey|WPS-PSKの鍵|
|priority|使用するアクセスポイントの優先度|
|status|ネットワークの状態|
|wepKeys|WEPキー|
|wepTxKeyIndex|WEPキーのインデックス|

### Wi-Fi接続情報の取得

接続中のWifi情報は、WifiManagerクラスのgetConnectionInfoメソッドで取得できる。
WiFiInfoクラスのインスタンスが返されるためgetterメソッドを値を参照できる

|||
|---|---|
|getBSSID|基本サービスセット識別子|
|getHiddenSSID|ステルスモードを示すフラグ|
|getIpAddress|IPアドレス|
|getLinkSpeed|リンクスピード|
|getMacAddress|MACアドレス|
|getNetworkId|ネットワークID|
|getRssi|受信信号強度|
|getSSID|無線LANの識別子|
|getSupplicantState|ネットワークとの接続ステータス|

### Wi-Fiの利用許可

Wi-Fiの状態を取得するにはマニフェストファイルのandroid.permission.ACCESS_WIFI_STATEのパーミッションを設定
Wi-Fiの設定変更にはandroid.permission.CHANGE_WIFI_STATEのパーミッションを設定

#####　WEPとは

無線LAN通信で使用される暗号化技術。すでに古いため、WPAやWPA2などのより強固なものが使用されることが多い。