org.wso2.iot.agent.services.NetworkInfoService.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.iot.agent.services.NetworkInfoService.java

Source

/*
 * Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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 org.wso2.iot.agent.services;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.wso2.iot.agent.AndroidAgentException;
import org.wso2.iot.agent.beans.Device;
import org.wso2.iot.agent.utils.Constants;

import java.util.ArrayList;
import java.util.List;

public class NetworkInfoService extends Service {

    private static final String TAG = NetworkInfoService.class.getSimpleName();

    private static int cellSignalStrength = 99; // Invalid signal strength is represented with 99.
    private static ObjectMapper mapper;
    private static NetworkInfo info;
    private static List<ScanResult> wifiScanResults;
    private static NetworkInfoService thisInstance;
    private WifiManager wifiManager;
    private TelephonyManager telephonyManager;

    private static final int DEFAULT_AGE = 0;
    private static final String MAC_ADDRESS = "macAddress";
    private static final String SIGNAL_STRENGTH = "signalStrength";
    private static final String AGE = "age";
    private static final String CHANNEL = "channel";
    private static final String SNR = "signalToNoiseRatio";
    private final IBinder mBinder = new NetworkInfoService.LocalBinder();

    private PhoneStateListener deviceNetworkStatusListener = new PhoneStateListener() {
        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            super.onSignalStrengthsChanged(signalStrength);
            if (signalStrength.isGsm()) {
                if (signalStrength.getGsmSignalStrength() != 99) {
                    // this is the equation used to convert a valid gsm signal to dbm.
                    setCellSignalStrength(signalStrength.getGsmSignalStrength() * 2 - 113);
                } else {
                    setCellSignalStrength(signalStrength.getGsmSignalStrength());
                }
            } else {
                setCellSignalStrength(signalStrength.getCdmaDbm());
            }
        }
    };

    private BroadcastReceiver wifiScanReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Constants.DEBUG_MODE_ENABLED) {
                Log.d(TAG, "Wifi scan result found");
            }
            wifiScanResults = wifiManager.getScanResults();
        }
    };

    class LocalBinder extends Binder {
        NetworkInfoService getService() {
            return NetworkInfoService.this;
        }
    }

    public NetworkInfoService() {
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (Constants.DEBUG_MODE_ENABLED) {
            Log.d(TAG, "Starting service with ID: " + startId);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onCreate() {
        thisInstance = this;
        if (Constants.DEBUG_MODE_ENABLED) {
            Log.d(TAG, "Creating service");
        }
        mapper = new ObjectMapper();
        info = getNetworkInfo();
        telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(deviceNetworkStatusListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
        wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (Constants.WIFI_SCANNING_ENABLED) {
            // Register broadcast receiver
            // Broadcast receiver will automatically call when number of wifi connections changed
            registerReceiver(wifiScanReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
            // start scanning wifi
            startWifiScan();
        }
    }

    @Override
    public void onDestroy() {
        telephonyManager.listen(deviceNetworkStatusListener, PhoneStateListener.LISTEN_NONE);
        if (Constants.WIFI_SCANNING_ENABLED) {
            unregisterReceiver(wifiScanReceiver);
        }
        thisInstance = null;
        if (Constants.DEBUG_MODE_ENABLED) {
            Log.d(TAG, "Service destroyed.");
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * Network data such as  connection type and signal details can be fetched with this method.
     *
     * @return String representing network details.
     * @throws AndroidAgentException
     */
    public static String getNetworkStatus() throws AndroidAgentException {
        if (thisInstance == null) {
            Log.e(TAG, "Service not instantiated");
            throw new AndroidAgentException(TAG + " is not started.");
        }
        info = thisInstance.getNetworkInfo();
        String payload = null;
        if (info != null) {
            List<Device.Property> properties = new ArrayList<>();
            Device.Property property = new Device.Property();
            property.setName(Constants.Device.CONNECTION_TYPE);
            property.setValue(info.getTypeName());
            properties.add(property);

            if ((info.isConnected())) {
                if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
                    property = new Device.Property();
                    property.setName(Constants.Device.MOBILE_CONNECTION_TYPE);
                    property.setValue(info.getSubtypeName());
                    properties.add(property);
                } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {
                    property = new Device.Property();
                    property.setName(Constants.Device.WIFI_SSID);
                    // NetworkInfo API of Android seem to add extra "" to SSID, therefore escaping it.
                    property.setValue(String.valueOf(thisInstance.getWifiSSID()).replaceAll("\"", ""));
                    properties.add(property);

                    property = new Device.Property();
                    property.setName(Constants.Device.WIFI_SIGNAL_STRENGTH);
                    property.setValue(String.valueOf(thisInstance.getWifiSignalStrength()));
                    properties.add(property);
                }
            }

            property = new Device.Property();
            property.setName(Constants.Device.MOBILE_SIGNAL_STRENGTH);
            property.setValue(String.valueOf(getCellSignalStrength()));
            properties.add(property);

            try {
                payload = mapper.writeValueAsString(properties);
            } catch (JsonProcessingException e) {
                String errorMsg = "Error occurred while parsing " + "network property property object to json.";
                Log.e(TAG, errorMsg, e);
                throw new AndroidAgentException(errorMsg, e);
            }
        }
        return payload;
    }

    public static int getCellSignalStrength() {
        return cellSignalStrength;
    }

    public static void setCellSignalStrength(int cellSignalStrength) {
        NetworkInfoService.cellSignalStrength = cellSignalStrength;
    }

    public static String getWifiScanResult() throws AndroidAgentException {
        if (wifiScanResults != null) {
            try {
                JSONArray scanResults = new JSONArray();
                JSONObject scanResult;
                for (ScanResult result : wifiScanResults) {
                    scanResult = new JSONObject();
                    scanResult.put(MAC_ADDRESS, result.BSSID);
                    scanResult.put(SIGNAL_STRENGTH, result.level);
                    scanResult.put(AGE, DEFAULT_AGE);
                    scanResult.put(CHANNEL, result.frequency);
                    scanResult.put(SNR, result.level); // temporarily added
                    scanResults.put(scanResult);
                }
                if (Constants.DEBUG_MODE_ENABLED) {
                    Log.d(TAG, "Wifi scan result: " + scanResults.toString());
                }
                // scanning for next round
                thisInstance.startWifiScan();
                return scanResults.toString();
            } catch (JSONException e) {
                String msg = "Error occurred while retrieving wifi scan results";
                Log.e(TAG, msg, e);
                throw new AndroidAgentException(msg);
            }
        }
        return null;
    }

    private int getWifiSignalStrength() {
        if (wifiManager != null) {
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            return wifiInfo.getRssi();
        }
        return -1;
    }

    private String getWifiSSID() {
        if (wifiManager != null) {
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            return wifiInfo.getSSID();
        }
        return null;
    }

    private void startWifiScan() {
        if (Constants.DEBUG_MODE_ENABLED) {
            Log.d(TAG, "Wifi scanning started...");
        }
        wifiManager.startScan();
    }

    private NetworkInfo getNetworkInfo() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(
                Context.CONNECTIVITY_SERVICE);
        return connectivityManager.getActiveNetworkInfo();
    }
}