2

I have trouble with managing correctly Internet connection on new Android versions when device is unlocked with enabled battery saver.

android.permission.INTERNET and android.permission.ACCESS_NETWORK_STATE permissions are added to the manifest file.

I register broadcast received to listen ConnectivityManager.CONNECTIVITY_ACTION when Activity is started and unregister when stoped. It works perfect when manually disable\enable Wi-FI or cellular connection.

Also I use method to check connection

   private boolean isNetworkAvailable() {
      ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
      NetworkInfo networkInfo = conn.getActiveNetworkInfo();
      return null != networkInfo && networkInfo.isConnected();
   }

Every time when phone is unlocked and my application is on the foreground isNetworkAvailable() method returns is connected but it is not.

I tried to implement something like ping logic but after unlock the phone I receive not connected all time till disable battery saver mode

    try {
        InetAddress inetAddress = InetAddress.getByName("www.google.com");
        if (inetAddress.isReachable(1000)) {
            // IS CONNECTED
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    // IS NOT CONNECTED

Does someone know good solution how to handle connection on Android 7 & Android 8?

Thanks beforehand

Source code Activity:

public class MainActivity extends AppCompatActivity implements ConnectionManager.ConnectionStatusListener {

private TextView textView;

private ConnectionManager cm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.textView);
    cm = new ConnectionManager(getBaseContext());
    //Show by default is disconnected
    disconnected();
}

@Override
protected void onStart() {
    super.onStart();
    cm.register(this);
}

@Override
protected void onStop() {
    super.onStop();
    cm.unregister(this);
}


// ConnectionManager.ConnectionStatusListener  implementation
@Override
public void connected() {
    textView.setText("Connected");
    textView.setTextColor(Color.GREEN);
}

@Override
public void disconnected() {
    textView.setText("Disconnected");
    textView.setTextColor(Color.RED);
}
}

My implementation of connection manager:

class ConnectionManager {
private final Context context;
private final Object syncObj = new Object();
private final LinkedList<ConnectionStatusListener> listeners = new LinkedList<>();
private final Handler uiHandler;
private final Handler ioHandler;


private final BroadcastReceiver connectivityActionBR = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        updateConnStatus();
    }
};
private final Runnable pingRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            InetAddress inetAddress = InetAddress.getByName("www.google.com");
            if (!inetAddress.isReachable(1000)) {
                notifyListeners(false);
                startPingServerDelayed(500);
            } else {
                notifyListeners(true);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
};

public ConnectionManager(Context context) {
    this.context = context;

    uiHandler = new Handler();

    HandlerThread handlerThread = new HandlerThread("checkInternetConnectionThread");
    handlerThread.start();
    ioHandler = new Handler(handlerThread.getLooper());
    // TODO: 9/18/17 add destroy to stop threadHandler
}


public void register(ConnectionStatusListener listener) {
    synchronized (syncObj) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }

        registerBR();
    }
}

public void unregister(ConnectionStatusListener listener) {
    synchronized (syncObj) {
        listeners.remove(listener);
    }

    unregisterBR();
    stopPingServer();
}


private void registerBR() {
    context.registerReceiver(connectivityActionBR, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}

private void unregisterBR() {
    context.unregisterReceiver(connectivityActionBR);
}

private void notifyListeners(final boolean isConnected) {
    Log.e("---", "isConnected=" + isConnected);
    uiHandler.post(new Runnable() {
        @Override
        public void run() {
            synchronized (syncObj) {
                for(ConnectionStatusListener listener : listeners) {
                    if (isConnected) {
                        listener.connected();
                    } else {
                        listener.disconnected();
                    }
                }
            }
        }
    });

}

private void updateConnStatus() {
    if (!isNetworkAvailable()) {
        stopPingServer();
        notifyListeners(false);
    }

    startPingServerNow();
}

private void startPingServerDelayed(long millis) {
    ioHandler.postDelayed(pingRunnable, millis);
}
private void startPingServerNow() {
    ioHandler.post(pingRunnable);
}

private void stopPingServer() {
    ioHandler.removeCallbacks(pingRunnable);
}

private boolean isNetworkAvailable() {
    ConnectivityManager conn = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = conn.getActiveNetworkInfo();
    return null != networkInfo && networkInfo.isConnectedOrConnecting();
}


public interface ConnectionStatusListener {
    void connected();

    void disconnected();
}
}
Dmytro Batyuk
  • 957
  • 8
  • 15

1 Answers1

0

Register your broadcast in onCreate() and unregister it in onDestroy(). Let me, what you have has to work.

Pedro Varela
  • 2,296
  • 1
  • 26
  • 32
  • It doesn't help because when I register BR under onCreate() onReceive() calls just once when was received – Dmytro Batyuk Sep 18 '17 at 20:41
  • any suggestions? – Dmytro Batyuk Sep 19 '17 at 20:00
  • I have the same code you have. And i registered my BR in onCreate as I said., but maybe is the device you are using to testing. Have you tried in another device? The reason why you must put it there, is because you create your activity and it will always exists at least you kill it. – Pedro Varela Sep 19 '17 at 20:03
  • I copy and paste all of your code and it works as expected, so it might be your phone.09-19 16:16:54.717 E/---: isConnected=true 09-19 16:17:04.001 E/---: isConnected=true 09-19 16:17:08.203 E/---: isConnected=true 09-19 16:17:15.942 E/---: isConnected=true 09-19 16:17:22.082 E/---: isConnected=true 09-19 16:17:27.562 E/---: isConnected=false 09-19 16:17:37.142 E/---: isConnected=true 09-19 16:18:16.427 E/---: isConnected=true 09-19 16:18:19.283 E/---: isConnected=true – Pedro Varela Sep 19 '17 at 20:18
  • In case you have pasted code from my code snippet there is one place when there is no connection. 09-19 16:17:22.082 E/---: isConnected=true 09-19 16:17:27.562 E/---: isConnected=false - this one 09-19 16:17:37.142 E/---: isConnected=true In my code snippet I'm checking connection onStart I'm using Nexus 6P with enabled Battery Saver – Dmytro Batyuk Sep 20 '17 at 20:21
  • that is because I set my phone to Airplane Mode. I have a nexus 6P too – Pedro Varela Sep 20 '17 at 20:35