OSDN Git Service

Wifiの接続についてちょっと改善。
[gokigen/A01c.git] / wear / src / main / java / jp / sfjp / gokigen / a01c / WifiConnection.kt
1 package jp.sfjp.gokigen.a01c
2
3 import android.content.BroadcastReceiver
4 import android.content.Context
5 import android.content.Intent
6 import android.content.IntentFilter
7 import android.net.ConnectivityManager
8 import android.net.ConnectivityManager.NetworkCallback
9 import android.net.Network
10 import android.net.NetworkCapabilities
11 import android.net.NetworkRequest
12 import android.net.wifi.WifiManager
13 import android.os.Handler
14 import android.os.Looper
15 import android.os.Message
16 import android.util.Log
17 import androidx.appcompat.app.AppCompatActivity
18 import java.util.concurrent.TimeUnit
19
20 class WifiConnection(private val context: AppCompatActivity, private val callback : IWifiConnection)
21 {
22     private var isWatchingWifiStatus = false
23
24     private val connectivityManager: ConnectivityManager = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
25     private val connectionReceiver: BroadcastReceiver = object : BroadcastReceiver()
26     {
27         override fun onReceive(context: Context, intent: Intent)
28         {
29             onReceiveBroadcastOfConnection(context, intent)
30         }
31     }
32
33     private val networkConnectionTimeoutHandler = object : Handler(Looper.getMainLooper())
34     {
35         override fun handleMessage(msg: Message)
36         {
37             when (msg.what) {
38                 MESSAGE_CONNECTIVITY_TIMEOUT -> {
39                     Log.d(TAG, "Network connection timeout")
40                     unregisterNetworkCallback()
41                 }
42             }
43         }
44     }
45
46     private val networkCallback = object : NetworkCallback()
47     {
48         override fun onAvailable(network: Network) {
49             networkConnectionTimeoutHandler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT)
50             context.runOnUiThread {
51                 if (!connectivityManager.bindProcessToNetwork(network))
52                 {
53                     Log.e(TAG, "ConnectivityManager.bindProcessToNetwork()  requires android.permission.INTERNET")
54                 }
55                 else
56                 {
57                     Log.d(TAG, "Network available")
58                 }
59             }
60         }
61
62         override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities)
63         {
64             Log.d(TAG, "Network capabilities changed")
65         }
66
67         override fun onLost(network: Network)
68         {
69             Log.d(TAG, "Network lost")
70         }
71     }
72
73
74     init
75     {
76         Log.v(TAG, "WifiConnection()")
77         requestHighBandwidthNetwork()
78 /*
79         Network activeNetwork = connectivityManager.getActiveNetwork();
80         if (activeNetwork != null)
81         {
82             int bandwidth = connectivityManager.getNetworkCapabilities(activeNetwork).getLinkDownstreamBandwidthKbps();
83             if (bandwidth < MIN_BANDWIDTH_KBPS)
84             {
85                 // Request a high-bandwidth network
86             }
87         }
88         else
89         {
90             // You already are on a high-bandwidth network, so start your network request
91         }
92 */
93
94 /*
95         Network activeNetwork = connectivityManager.getActiveNetwork();
96         if (activeNetwork != null)
97         {
98             int bandwidth = connectivityManager.getNetworkCapabilities(activeNetwork).getLinkDownstreamBandwidthKbps();
99             if (bandwidth < MIN_BANDWIDTH_KBPS)
100             {
101                 // Request a high-bandwidth network
102             }
103         }
104         else
105         {
106             // You already are on a high-bandwidth network, so start your network request
107         }
108 */
109      }
110
111     // Determine if there is a high-bandwidth network exists. Checks both the active
112     // and bound networks. Returns false if no network is available (low or high-bandwidth).
113     private fun isNetworkHighBandwidth(): Boolean
114     {
115         var network: Network? = connectivityManager.boundNetworkForProcess
116         network = network ?: connectivityManager.activeNetwork
117         if (network == null)
118         {
119             return (false)
120         }
121         val networkCapabilities = connectivityManager.getNetworkCapabilities(network) ?: return (false)
122         return (networkCapabilities.linkDownstreamBandwidthKbps >= MIN_NETWORK_BANDWIDTH_KBPS)
123     }
124
125
126     private fun unregisterNetworkCallback()
127     {
128         Log.d(TAG, "Unregistering network callback")
129         connectivityManager.unregisterNetworkCallback(networkCallback)
130     }
131
132     private fun releaseHighBandwidthNetwork()
133     {
134         connectivityManager.bindProcessToNetwork(null)
135         unregisterNetworkCallback()
136     }
137
138     private fun addWifiNetwork()
139     {
140         // requires android.permission.CHANGE_WIFI_STATE
141         context.applicationContext.startActivity(Intent(ACTION_ADD_NETWORK_SETTINGS))
142     }
143
144     /**
145      * Wifiが使える状態だったら、カメラと接続して動作するよ
146      *
147      */
148     @Suppress("DEPRECATION")
149     private fun onReceiveBroadcastOfConnection(context: Context, intent: Intent)
150     {
151         Log.v(TAG, context.getString(R.string.connect_check_wifi))
152         try
153         {
154             val action = intent.action
155             if (action == ConnectivityManager.CONNECTIVITY_ACTION)
156             {
157                 val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
158                 val info = wifiManager.connectionInfo
159                 if (wifiManager.isWifiEnabled)
160                 {
161                     if ((info != null)&&(info.networkId != -1))
162                     {
163                         Log.v(TAG, " READY TO CONNECT CAMERA. " + info.networkId)
164                     }
165                     callback.onConnectedToWifi()
166                 }
167             }
168         }
169         catch (e : Exception)
170         {
171             e.printStackTrace()
172         }
173     }
174
175     fun requestNetwork()
176     {
177         Log.v(TAG, " requestNetwork()")
178         requestHighBandwidthNetwork()
179     }
180
181     /**
182      * Wifi接続状態の監視
183      * (接続の実処理は onReceiveBroadcastOfConnection() で実施)
184      */
185     fun startWatchWifiStatus()
186     {
187         Log.v(TAG, "startWatchWifiStatus()")
188         val filter = IntentFilter()
189         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION)
190         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
191         context.registerReceiver(connectionReceiver, filter)
192         isWatchingWifiStatus = true
193     }
194
195     /**
196      * Wifi接続状態の監視終了
197      */
198     fun stopWatchWifiStatus()
199     {
200         Log.v(TAG, "stopWatchWifiStatus()")
201         context.unregisterReceiver(connectionReceiver)
202         isWatchingWifiStatus = false
203     }
204
205     /**
206      * Wifi接続状態の監視処理を行っているかどうか
207      *
208      * @return true : 監視中 / false : 停止中
209      */
210     fun isWatchWifiStatus(): Boolean
211     {
212         return isWatchingWifiStatus
213     }
214
215     private fun requestHighBandwidthNetwork()
216     {
217         try
218         {
219             val bandwidth: Int = connectivityManager.activeNetwork?.let { activeNetwork ->
220                 connectivityManager.getNetworkCapabilities(activeNetwork)?.linkDownstreamBandwidthKbps
221             } ?: -1
222             Log.v(TAG, " requestHighBandwidthNetwork() (Bandwidth: $bandwidth)")
223             when
224             {
225                 bandwidth < 0 -> {
226                     // No active network
227                 }
228                 bandwidth in (0 until MIN_NETWORK_BANDWIDTH_KBPS) -> {
229                     // Request a high-bandwidth network
230                 }
231                 else -> {
232                     // すでにつながっているので、何もしない。
233                     Log.d(TAG, " already connected with high-bandwidth network")
234                     return
235                 }
236             }
237
238             // Before requesting a high-bandwidth network, ensure prior requests are invalidated.
239             unregisterNetworkCallback()
240             Log.d(TAG, "requestHighBandwidthNetwork(): Requesting high-bandwidth network")
241
242             // Requesting an unmetered network may prevent you from connecting to the cellular
243             // network on the user's watch or phone; however, unless you explicitly ask for permission
244             // to a access the user's cellular network, you should request an unmetered network.
245             val request = NetworkRequest.Builder()
246                     .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
247                     .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
248                     .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
249                     .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
250                     .build()
251
252             // requires android.permission.CHANGE_NETWORK_STATE
253             connectivityManager.requestNetwork(request, networkCallback)
254             networkConnectionTimeoutHandler.sendMessageDelayed(networkConnectionTimeoutHandler.obtainMessage(MESSAGE_CONNECTIVITY_TIMEOUT), NETWORK_CONNECTIVITY_TIMEOUT_MS)
255         }
256         catch (e : Exception)
257         {
258             e.printStackTrace()
259         }
260     }
261
262     companion object
263     {
264         private val TAG = WifiConnection::class.java.simpleName
265         private const val MESSAGE_CONNECTIVITY_TIMEOUT = 1
266         private const val MIN_NETWORK_BANDWIDTH_KBPS = 10000
267         private const val ACTION_ADD_NETWORK_SETTINGS = "com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS"
268         private val NETWORK_CONNECTIVITY_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(2000)
269     }
270 }