How to check if Google Glass is connected to inter

2019-02-25 09:15发布

问题:

Is there a way to detect if Google Glass is connected to the internet at runtime? For instance, I often get the message "Can't reach Google right now" when using voice input in my app. Instead, I would like to preemptively intercept the condition that would cause that message and use default values rather than ask for voice input. After searching for a while, the only thing I could find was a solution to the same question for Android in general:

private boolean isConnected() {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

I tried using this for my Glassware but it doesn't seem to work (I turned off the wifi and data but isConnected() still returns true even though I get the "Can't reach Google right now" message). Does anyone know if the GDK has a way to do this? Or should something similar to the above method work?

EDIT: Here's my eventual solution, based partially on the answer by EntryLevelDev below.

I had to use a background thread to use HTTP GET requests to avoid getting a NetworkOnMainThreadException, so I decided to have it run every few seconds and update a local isConnected variable:

public static boolean isConnected = false;

public boolean isDeviceConnectedToInternet() {
    return isConnected;
}

private class CheckConnectivityTask extends AsyncTask<Void, Boolean, Boolean> {
    protected Boolean doInBackground(Void... voids) {
        while(true) {
            // Update isConnected variable.
            publishProgress(isConnected());
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Determines if the Glassware can access the internet.
     * isNetworkAvailable() is used first because there is no point in executing an HTTP GET
     * request if ConnectivityManager and NetworkInfo tell us that no network is available.
     */
    private boolean isConnected(){
        if (isNetworkAvailable()) {
            HttpGet httpGet = new HttpGet("http://www.google.com");
            HttpParams httpParameters = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
            HttpConnectionParams.setSoTimeout(httpParameters, 5000);

            DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
            try{
                Log.d(LOG_TAG, "Checking network connection...");
                httpClient.execute(httpGet);
                Log.d(LOG_TAG, "Connection OK");
                return true;
            }
            catch(ClientProtocolException e){
                e.printStackTrace();
            }
            catch(IOException e){
                e.printStackTrace();
            }
            Log.d(LOG_TAG, "Connection unavailable");
        } else {
            // No connection; for Glass this probably means Bluetooth is disconnected.
            Log.d(LOG_TAG, "No network available!");
        }
        return false;
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager
                = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        Log.d(LOG_TAG, String.format("In isConnected(), activeNetworkInfo.toString(): %s",
                activeNetworkInfo == null ? "null" : activeNetworkInfo.toString()));
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
    }

    protected void onProgressUpdate(Boolean... isConnected) {
        DecisionMakerService.isConnected = isConnected[0];
        Log.d(LOG_TAG, "Checking connection: connected = " + isConnected[0]);
    }
}

To start it, call new CheckConnectivityTask().execute(); (probably from onCreate()). I also had to add these to my Android.manifest:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

回答1:

If Glass connects to a phone with Bluetooth, your method returns true even when your phone has no WiFi and data connection.

I guess it's a correct behavior. getActiveNetworkInfo is more about a connection via available interfaces. It's not really about connection to the internet. It's like connecting to a router doesn't mean you connect to the internet.

NOTE (from the doc):

getActiveNetworkInfo returns

"a NetworkInfo object for the current default network or null if no network default network is currently active"

To check the internet connection, you might try ping Google instead though I think there might be a better way to check.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    new Thread(new Runnable() {

        @Override
        public void run() {
            Log.v(MainActivity.class.getSimpleName(), "isGoogleReachable : "
                    + isGoogleReachable());
        }

    }).start();;

}
private boolean isGoogleReachable() {
    try {
        if (InetAddress.getByName("www.google.com").isReachable(5000)) {
            return true;
        } else {
            return false;
        }
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return false;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return false;
    }
}

Add this permission:

<uses-permission android:name="android.permission.INTERNET" />

EDIT: Or you could try this:

public static void isNetworkAvailable(Context context){
    HttpGet httpGet = new HttpGet("http://www.google.com");
    HttpParams httpParameters = new BasicHttpParams();
    // Set the timeout in milliseconds until a connection is established.
    // The default value is zero, that means the timeout is not used.
    int timeoutConnection = 3000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    // Set the default socket timeout (SO_TIMEOUT)
    // in milliseconds which is the timeout for waiting for data.
    int timeoutSocket = 5000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);
    try{
        Log.d(TAG, "Checking network connection...");
        httpClient.execute(httpGet);
        Log.d(TAG, "Connection OK");
        return;
    }
    catch(ClientProtocolException e){
        e.printStackTrace();
    }
    catch(IOException e){
        e.printStackTrace();
    }

    Log.d(TAG, "Connection unavailable");
}

Also see:

Detect if Android device has Internet connection

"should something similar to the above method work?"

Yes, it works fine if Bluetooth is also off.



回答2:

When you have wifi and data turned off, what is the network type name that activeNetworkInfo.getTypeName() returns?

This might be a bug — can you dump as much info as possible out of the NetworkInfo object (especially the type name, DetailedState enumeration, and so forth) and file it in our issue tracker?