You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
340 lines
13 KiB
340 lines
13 KiB
/*
|
|
* Copyright (C) 2016 Google Inc. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package com.example.android.wearable.wear.wearhighbandwidthnetworking;
|
|
|
|
import android.app.Activity;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.net.ConnectivityManager;
|
|
import android.net.Network;
|
|
import android.net.NetworkCapabilities;
|
|
import android.net.NetworkRequest;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.util.Log;
|
|
import android.view.View;
|
|
import android.view.WindowManager;
|
|
import android.widget.ImageView;
|
|
import android.widget.TextView;
|
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
/**
|
|
* This sample demonstrates how to determine if a high-bandwidth network is available for use cases
|
|
* that require a minimum network bandwidth, such as streaming media or downloading large files.
|
|
* In addition, the sample demonstrates best practices for asking a user to add a new Wi-Fi network
|
|
* for high-bandwidth network operations, if currently available networks are inadequate.
|
|
*/
|
|
public class MainActivity extends Activity {
|
|
private static final String LOG_TAG = MainActivity.class.getSimpleName();
|
|
|
|
// Intent action for sending the user directly to the add Wi-Fi network activity.
|
|
private static final String ACTION_ADD_NETWORK_SETTINGS =
|
|
"com.google.android.clockwork.settings.connectivity.wifi.ADD_NETWORK_SETTINGS";
|
|
|
|
// Message to notify the network request timout handler that too much time has passed.
|
|
private static final int MESSAGE_CONNECTIVITY_TIMEOUT = 1;
|
|
|
|
// How long the app should wait trying to connect to a sufficient high-bandwidth network before
|
|
// asking the user to add a new Wi-Fi network.
|
|
private static final long NETWORK_CONNECTIVITY_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
|
|
|
|
// The minimum network bandwidth required by the app for high-bandwidth operations.
|
|
private static final int MIN_NETWORK_BANDWIDTH_KBPS = 10000;
|
|
|
|
private ConnectivityManager mConnectivityManager;
|
|
private ConnectivityManager.NetworkCallback mNetworkCallback;
|
|
|
|
// Handler for dealing with network connection timeouts.
|
|
private Handler mHandler;
|
|
|
|
private ImageView mConnectivityIcon;
|
|
private TextView mConnectivityText;
|
|
|
|
private View mButton;
|
|
private ImageView mButtonIcon;
|
|
private TextView mButtonText;
|
|
private TextView mInfoText;
|
|
private View mProgressBar;
|
|
|
|
// Tags added to the button in the UI to detect what operation the user has requested.
|
|
// These are required since the app reuses the button for different states of the app/UI.
|
|
// See onButtonClick() for how these tags are used.
|
|
static final String TAG_REQUEST_NETWORK = "REQUEST_NETWORK";
|
|
static final String TAG_RELEASE_NETWORK = "RELEASE_NETWORK";
|
|
static final String TAG_ADD_WIFI = "ADD_WIFI";
|
|
|
|
// These constants are used by setUiState() to determine what information to display in the UI,
|
|
// as this app reuses UI components for the various states of the app, which is dependent on
|
|
// the state of the network.
|
|
static final int UI_STATE_REQUEST_NETWORK = 1;
|
|
static final int UI_STATE_REQUESTING_NETWORK = 2;
|
|
static final int UI_STATE_NETWORK_CONNECTED = 3;
|
|
static final int UI_STATE_CONNECTION_TIMEOUT = 4;
|
|
|
|
@Override
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
setContentView(R.layout.activity_main);
|
|
|
|
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
|
|
|
mConnectivityIcon = (ImageView) findViewById(R.id.connectivity_icon);
|
|
mConnectivityText = (TextView) findViewById(R.id.connectivity_text);
|
|
|
|
mProgressBar = findViewById(R.id.progress_bar);
|
|
|
|
mButton = findViewById(R.id.button);
|
|
mButton.setTag(TAG_REQUEST_NETWORK);
|
|
mButtonIcon = (ImageView) findViewById(R.id.button_icon);
|
|
mButtonText = (TextView) findViewById(R.id.button_label);
|
|
|
|
mInfoText = (TextView) findViewById(R.id.info_text);
|
|
|
|
mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
|
|
mHandler = new Handler() {
|
|
@Override
|
|
public void handleMessage(Message msg) {
|
|
switch (msg.what) {
|
|
case MESSAGE_CONNECTIVITY_TIMEOUT:
|
|
Log.d(LOG_TAG, "Network connection timeout");
|
|
setUiState(UI_STATE_CONNECTION_TIMEOUT);
|
|
unregisterNetworkCallback();
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
public void onStop() {
|
|
releaseHighBandwidthNetwork();
|
|
super.onStop();
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
|
|
if (isNetworkHighBandwidth()) {
|
|
setUiState(UI_STATE_NETWORK_CONNECTED);
|
|
} else {
|
|
setUiState(UI_STATE_REQUEST_NETWORK);
|
|
}
|
|
}
|
|
|
|
private void unregisterNetworkCallback() {
|
|
if (mNetworkCallback != null) {
|
|
Log.d(LOG_TAG, "Unregistering network callback");
|
|
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
|
mNetworkCallback = null;
|
|
}
|
|
}
|
|
|
|
// Determine if there is a high-bandwidth network exists. Checks both the active
|
|
// and bound networks. Returns false if no network is available (low or high-bandwidth).
|
|
private boolean isNetworkHighBandwidth() {
|
|
Network network = mConnectivityManager.getBoundNetworkForProcess();
|
|
network = network == null ? mConnectivityManager.getActiveNetwork() : network;
|
|
if (network == null) {
|
|
return false;
|
|
}
|
|
|
|
// requires android.permission.ACCESS_NETWORK_STATE
|
|
int bandwidth = mConnectivityManager
|
|
.getNetworkCapabilities(network).getLinkDownstreamBandwidthKbps();
|
|
|
|
if (bandwidth >= MIN_NETWORK_BANDWIDTH_KBPS) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private void requestHighBandwidthNetwork() {
|
|
// Before requesting a high-bandwidth network, ensure prior requests are invalidated.
|
|
unregisterNetworkCallback();
|
|
|
|
Log.d(LOG_TAG, "Requesting high-bandwidth network");
|
|
|
|
// Requesting an unmetered network may prevent you from connecting to the cellular
|
|
// network on the user's watch or phone; however, unless you explicitly ask for permission
|
|
// to a access the user's cellular network, you should request an unmetered network.
|
|
NetworkRequest request = new NetworkRequest.Builder()
|
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
|
|
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
|
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
|
|
.build();
|
|
|
|
mNetworkCallback = new ConnectivityManager.NetworkCallback() {
|
|
@Override
|
|
public void onAvailable(final Network network) {
|
|
mHandler.removeMessages(MESSAGE_CONNECTIVITY_TIMEOUT);
|
|
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
// requires android.permission.INTERNET
|
|
if (!mConnectivityManager.bindProcessToNetwork(network)) {
|
|
Log.e(LOG_TAG, "ConnectivityManager.bindProcessToNetwork()"
|
|
+ " requires android.permission.INTERNET");
|
|
setUiState(UI_STATE_REQUEST_NETWORK);
|
|
} else {
|
|
Log.d(LOG_TAG, "Network available");
|
|
setUiState(UI_STATE_NETWORK_CONNECTED);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onCapabilitiesChanged(Network network,
|
|
NetworkCapabilities networkCapabilities) {
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
Log.d(LOG_TAG, "Network capabilities changed");
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onLost(Network network) {
|
|
Log.d(LOG_TAG, "Network lost");
|
|
|
|
runOnUiThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
setUiState(UI_STATE_REQUEST_NETWORK);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
// requires android.permission.CHANGE_NETWORK_STATE
|
|
mConnectivityManager.requestNetwork(request, mNetworkCallback);
|
|
|
|
mHandler.sendMessageDelayed(
|
|
mHandler.obtainMessage(MESSAGE_CONNECTIVITY_TIMEOUT),
|
|
NETWORK_CONNECTIVITY_TIMEOUT_MS);
|
|
}
|
|
|
|
private void releaseHighBandwidthNetwork() {
|
|
mConnectivityManager.bindProcessToNetwork(null);
|
|
unregisterNetworkCallback();
|
|
}
|
|
|
|
private void addWifiNetwork() {
|
|
// requires android.permission.CHANGE_WIFI_STATE
|
|
startActivity(new Intent(ACTION_ADD_NETWORK_SETTINGS));
|
|
}
|
|
|
|
/**
|
|
* Click handler for the button in the UI. The view tag is used to determine the specific
|
|
* function of the button.
|
|
*
|
|
* @param view The view that was clicked
|
|
*/
|
|
public void onButtonClick(View view) {
|
|
switch (view.getTag().toString()) {
|
|
case TAG_REQUEST_NETWORK:
|
|
requestHighBandwidthNetwork();
|
|
setUiState(UI_STATE_REQUESTING_NETWORK);
|
|
break;
|
|
|
|
case TAG_RELEASE_NETWORK:
|
|
releaseHighBandwidthNetwork();
|
|
setUiState(UI_STATE_REQUEST_NETWORK);
|
|
break;
|
|
|
|
case TAG_ADD_WIFI:
|
|
addWifiNetwork();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Sets the text and icons the connectivity indicator, button, and info text in the app UI,
|
|
// which are all reused for the various states of the app and network connectivity. Also,
|
|
// will show/hide a progress bar, which is dependent on the state of the network connectivity
|
|
// request.
|
|
private void setUiState(int uiState) {
|
|
switch (uiState) {
|
|
case UI_STATE_REQUEST_NETWORK:
|
|
if (isNetworkHighBandwidth()) {
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_happy);
|
|
mConnectivityText.setText(R.string.network_fast);
|
|
} else {
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_sad);
|
|
mConnectivityText.setText(R.string.network_slow);
|
|
}
|
|
|
|
mButton.setTag(TAG_REQUEST_NETWORK);
|
|
mButtonIcon.setImageResource(R.drawable.ic_fast_network);
|
|
mButtonText.setText(R.string.button_request_network);
|
|
mInfoText.setText(R.string.info_request_network);
|
|
|
|
break;
|
|
|
|
case UI_STATE_REQUESTING_NETWORK:
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_disconnected);
|
|
mConnectivityText.setText(R.string.network_connecting);
|
|
|
|
mProgressBar.setVisibility(View.VISIBLE);
|
|
mInfoText.setVisibility(View.GONE);
|
|
mButton.setVisibility(View.GONE);
|
|
|
|
break;
|
|
|
|
case UI_STATE_NETWORK_CONNECTED:
|
|
if (isNetworkHighBandwidth()) {
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_happy);
|
|
mConnectivityText.setText(R.string.network_fast);
|
|
} else {
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_sad);
|
|
mConnectivityText.setText(R.string.network_slow);
|
|
}
|
|
|
|
mProgressBar.setVisibility(View.GONE);
|
|
mInfoText.setVisibility(View.VISIBLE);
|
|
mButton.setVisibility(View.VISIBLE);
|
|
|
|
mButton.setTag(TAG_RELEASE_NETWORK);
|
|
mButtonIcon.setImageResource(R.drawable.ic_no_network);
|
|
mButtonText.setText(R.string.button_release_network);
|
|
mInfoText.setText(R.string.info_release_network);
|
|
|
|
break;
|
|
|
|
case UI_STATE_CONNECTION_TIMEOUT:
|
|
mConnectivityIcon.setImageResource(R.drawable.ic_cloud_disconnected);
|
|
mConnectivityText.setText(R.string.network_disconnected);
|
|
|
|
mProgressBar.setVisibility(View.GONE);
|
|
mInfoText.setVisibility(View.VISIBLE);
|
|
mButton.setVisibility(View.VISIBLE);
|
|
|
|
mButton.setTag(TAG_ADD_WIFI);
|
|
mButtonIcon.setImageResource(R.drawable.ic_wifi_network);
|
|
mButtonText.setText(R.string.button_add_wifi);
|
|
mInfoText.setText(R.string.info_add_wifi);
|
|
|
|
break;
|
|
}
|
|
}
|
|
} |