How to reliably detect an Internet connection at Android phone wake up - java

I have an App that relies on Internet connection at startup, and I am able to detect that ok with the code below.
However when the phone has been idle for some time and I unlock it and start my app it does not find the connection immediately and I have to re-start the app again to get success.
I have tried waiting in a thread and retrying the code below again with no success too.
Any ideas would be appreciated, thank you.
Code
// check Network/Internet connection
public boolean isOnline() {
try {
ConnectivityManager cm = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean haveConnectedWifi = false;
boolean haveConnectedMobile = false;
cm = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] netInfo = cm.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if (ni.getTypeName().equalsIgnoreCase("WIFI")) {
if (ni.isConnected()) {
haveConnectedWifi = true;
}
}
if (ni.getTypeName().equalsIgnoreCase("MOBILE")) {
if (ni.isConnected()) {
haveConnectedMobile = true;
}
}
}
return haveConnectedWifi || haveConnectedMobile;
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return false;
}

Put your code in the onResume() of your activity. That way it'll be checked each time you return to the activity.
Additionally, add a flag to know whether to check for the connection, and set that flag to true in the onPause() of your activity. Reset it to false in your onResume().
Something like:
boolean check;
protected void onCreate(Bundle blah) {
super(blah);
check = true;
// whatever else
}
protected void onResume() {
if(check) {
isOnline();
// Everything else
check = false;
}
super.onResume();
}
protected void onPause() {
check = true;
super.onPause();
}
EDIT: onResume() won't be called unless this activity is.. well being resumed, so you could just add:
protected void onResume() {
isOnline();
// Everything else
super.onResume();
}
Look at this flow chart from the Android dev site for a better understanding:

Related

How should I go ahead and check mobile data connectivity

I need a message to show up if there is no internet connection. Currently, if wifi is turn off then the toast method will work and won't move forward. However, if i turn on my mobile data even without a service plan, it will still open a blank activity.
here is the code i got from here
public static boolean isInternetAvailable(Context context)
{
NetworkInfo info = (NetworkInfo) ((ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
if (info == null)
{
Log.d(TAG,"no internet connection");
return false;
}
else
{
if(info.isConnected())
{
Log.d(TAG," internet connection available...");
return true;
}
else
{
Log.d(TAG," internet connection");
return true;
}
and this below is in my onClick method.
newsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(CheckNetwork.isInternetAvailable(MainActivity.this)) //returns true if internet available
{
moveToNews();
}
else
{
Toast.makeText(MainActivity.this,"Please Check Your Internet Connection and Try Again",Toast.LENGTH_LONG*4000).show();
}
To check internet connection -
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected();
}
In Menifest file -
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
check my below code
[1].Add below line internet permission into AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
[2]. On your MainActivity or Parent activity from you want to display or going to next activity add below code
[2.1] Globally declare below variable
private boolean isInternetConnected;
[2.2] add below line into onCreate()
isInternetConnected = isNetworkConnected(getApplicationContext());
[2.3] add below method
public boolean isNetworkConnected(Context context)
{
if(context != null)
{
ConnectivityManager cm = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm != null) {
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null) {
return false;
} else
return true;
}
else
{
return true;
}
}
else
{
return true;
}
}
[3]. add below code into onCreate() below of this line isInternetConnected = isNetworkConnected(getApplicationContext());
if(isInternetConnected){
//Move to another Activity or display Toast
}
else{
//Toast of not connected with Internet
}
THAT'S IT ;)!!

Allow switch to toggle only if internet connection is available

I have used a switch in my android code.
If internet service is available then only allow toggle else show a toast message. How do I achieve this?
I am unable to do so using
switch.setOnCheckedChangeListener().
The check is working only if I press the switch button twice.
aSwitch.setEnabled(false);
works only after I click once
First create a boolean that carries a flag :
boolean checkInternetFlag = false;
Then create a method that check if internet is available like this for example:
public final boolean isInternetOn() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
You will also need to add this permission in your manifest :
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Then you can do what you want in a condition like this :
checkInternetFlag = isInternetOn();
if (!checkInternetFlag) {
Toast.makeText(getActivity(), "Internet not available", Toast.LENGTH_LONG).show();
}
Also you can disable your toggle switch like this :
aSwitch.setEnabled(false);
And to make switch not clickable use :
aSwitch.setClickable(false);
The following method will catch if there is a change occured to networkstate:
1)Add this code to onCreate():
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
NetworkChangeReceiver receiver = new NetworkChangeReceiver();
registerReceiver(receiver, filter);
2) Add OnDestroy() Method:
#Override
protected void onDestroy() {
Log.v(LOG_TAG, "onDestory");
super.onDestroy();
unregisterReceiver(receiver);
}
3) Add the Following Code to your activity:
public class NetworkChangeReceiver extends BroadcastReceiver
{
#Override
public void onReceive(final Context context, final Intent intent)
{
Log.v(LOG_TAG, "Receieved notification about network status");
isNetworkAvailable(context);
}
private boolean isNetworkAvailable(Context context)
{
ConnectivityManager connectivity = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
{
for (int i = 0; i < info.length; i++)
{
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
if(!isConnected)
{
Log.v(LOG_TAG, "Now you are connected to Internet!");
aSwitch.setEnabled(true);
isConnected = true;
}
return true;
}
}
}
}
Toast.makeText(YourActivity.this, "Internet is not available", Toast.LENGTH_SHORT).show();
aSwitch.setEnabled(false);
isConnected = false;
return false;
}
}
4)Add this permission in your manifest file :
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Hopefully this relates to your requirement.

Android Service only runs whilst debugging

Background
I am creating a service that syncs a local Realm database (stored on phone) with an online database. The database stores users and measurements.
I initialise the service by calling 'startService(new Intent(this, SyncService.class));' during the splash activity's onCreate() method, and specify in the manifest that the service should run for the length of the application.
The service has a broadcast receiver. When the receiver detects a network change from 'not connected' to 'connected', it fires a method called syncDatabases().
This method finds all measurements recorded locally after the timestamp of the last API callback, and sends them to the database. The API responds to a request by returning the object + a unique ID.
When a measurement is made whilst the device is offline, it is stored locally. When an internet connection is made, the syncDatabases() method should be called in order to update the online server with the local measurements.
My steps...
Steps when debugging the project:
With wifi I open the app and with an external device make a new measurement. This appears on both the app and in the database. I then turn wifi off and make another measurement - this appears on the device.
I attach the debugger.
I turn back on wifi and this triggers the services' receivers' onReceive() method. I step through this and it all works according to plan. I reach the syncDatabases() method, and from there I receive the callback from the API, and it then updates the Realm database with the new ID value.
The problem...
If I don't attach the debugger, nothing happens. The new measurements aren't pushed to the database, and none of my Log.e calls are printed.
Why is this happening? And is there an alternative solution / fix for this problem?
Code
Service class
public class SyncService extends Service {
private static final String TAG = "SYNCSERVICE";
private boolean mConnected = false;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getExtras() != null) {
final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if (netInfo != null) {
switch (netInfo.getState()) {
case CONNECTED:
if (!mConnected) {
Log.e("NETWORK", "Network " + netInfo.getTypeName() + " now connected");
syncDatabases();
mConnected = true;
}
break;
default:
mConnected = false;
break;
}
} else mConnected = false;
}
}
};
#Override
public void onCreate() {
super.onCreate();
initReceiver();
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager.getActiveNetworkInfo() != null) {
mConnected = true;
}
android.util.Log.e(TAG, "onCreate: SyncService created");
}
#Override
public void onDestroy() {
super.onDestroy();
unInitReceiver();
android.util.Log.e(TAG, "onDestroy: SyncService destroyed");
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
android.util.Log.e(TAG, "onBind: SyncService bound");
return null;
}
#Override
public boolean onUnbind(Intent intent) {
android.util.Log.e(TAG, "onUnbind: SyncService unbound");
return super.onUnbind(intent);
}
#Override
public void onRebind(Intent intent) {
super.onRebind(intent);
android.util.Log.e(TAG, "onRebind: SyncService rebound");
}
private void initReceiver() {
IntentFilter filters = new IntentFilter();
filters.addAction("android.net.wifi.WIFI_STATE_CHANGED");
filters.addAction("android.net.wifi.STATE_CHANGE");
registerReceiver(mReceiver, filters);
}
private void unInitReceiver() {
unregisterReceiver(mReceiver);
}
public void syncDatabases() {
RealmResults<UserDB> users = RealmDB.getInstance(getApplicationContext()).where(UserDB.class).findAll();
if (users.size() > 0) {
int userId = users.get(0).getmUserID();
Log.e("MESSAGE", PreferenceUtils.getInstance().getLastSyncDate());
Date lastSync = null;
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.getDefault());
try {
lastSync = sdf.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e) {
e.printStackTrace();
try {
lastSync = BaseFragment.FORMAT.parse(PreferenceUtils.getInstance().getLastSyncDate());
}
catch (ParseException e1) {
e1.printStackTrace();
}
}
if (lastSync != null) {
Date lastSyncOffset = new Date(lastSync.getTime() + 1000);
/** Get all local results which have been made after the last sync date
 **/
RealmResults<MeasurementDB> newLocalMeasurements = RealmDB.getInstance(getApplicationContext())
.where(MeasurementDB.class).equalTo("user_ID", userId)
.greaterThan("dateCreated", lastSyncOffset)
.findAll();
/** For each measurement made after the last sync, add it to the server
 **/
for (MeasurementDB measurement : newLocalMeasurements) {
TemperatureListener mListener = new TemperatureListener(measurement);
ApiRequest.getInstance(getApplicationContext()).registerNewMeasurement(measurement.getAverage(),
measurement.getDateCreated().toString(), mListener, mListener);
}
}
}
}
/**
* Temperature listener receives the local copy of the temperature item. onResponse can then
* directly mutate the object instead of searching local db
*/
private class TemperatureListener implements Response.Listener<Measurement>, Response.ErrorListener {
private MeasurementDB measurement;
public TemperatureListener(MeasurementDB measurement) {
this.measurement = measurement;
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e("OnResponse", "Failure");
}
#Override
public void onResponse(Measurement response) {
Log.e("OnResponse", "Success");
/** Update our local measurement's ID value (supplied by server)
 **/
RealmDB.getInstance(getApplicationContext()).beginTransaction();
measurement.setMeasurement_ID(response.getmMeasurementId());
RealmDB.getInstance(getApplicationContext()).commitTransaction();
/** Update the last sync date
 **/
PreferenceUtils.getInstance().setLastSyncDate(response.getmDateCreated());
}
}
}
Initialisation of Service in splash activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mTimedOut = true;
finishActivity();
}
}, DURATION);
/** Will sync application / cloud databases in background of app when network connected. **/
startService(new Intent(this, SyncService.class));
doApiWork();
}
Manifest entry
Stop with task to kill the service at the same time as the app.
Exported 'false' stops other apps from using the service.
<service
android:name=".network.SyncService"
android:stopWithTask="true"
android:enabled="true"
android:exported="false"/>
EDIT
I removed the service and left a receiver class, registered in the manifest, which triggers methods on another class when needed. However the receiver is only triggered in debug mode.

what is the best way to check Internet connection continuously in android

I am developing an application. In that one screen check Internet connection, immediately after onCreate() method. If network connection is good i am calling one AsyncTask class for load countries list and show it on screen in spinnerView. If there is no network connection i am showing Toast Message to User and call check_Network(AsyncTask). In this class protected Long doInBackground(URL... params) method i'm checking Network connected or not if connected call countries AsyncTask otherwise again i am calling check_Network(AsyncTask). this process repeat until network is connected. my problem is It is correct way for Check Network Repeatedly. please suggested me. sorry i am poor in english please understand.blow i am showing my code
if (CheckNetwork.isOnline(this)) {
try {
new CountryProcess().execute();
} catch (Exception e) {
e.printStackTrace();
}
} else {
Toast.makeText(
getApplicationContext(),
getString(R.string.network_connection_fail)
+ "!", Toast.LENGTH_LONG).show();
new NetWork_connectivity().execute();
}
//.......................//
class NetWork_connectivity extends AsyncTask<URL, Integer,Long>
{
#Override
protected Long doInBackground(URL... params)
{
if (CheckNetwork.isOnline(MainActivity.this)) {
new CountryProcess().execute();
}else
{
new NetWork_connectivity().execute();
}
return null;
}
}
Add below code in manifest, for adding receiver with connectivity change intent
<receiver android:name=".NetworkStateReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
And at receiver side, get extras associated with intent and check for status. So whenever there is change in network status, you will be notified then perform your task accordingly.
public class NetworkStateReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getExtras()!=null) {
NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
//connected
}
}
if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
//not connected
}
}
}
For your case, you would like to add permission in manifest and register receiver in your activity.
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(networkReceiver, filter);
Make sure to unregister it as well before leaving activity with
unregisterReceiver(networkReceiver);
private BroadcastReceiver networkReceiver = new BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if(intent.getExtras()!=null) {
NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
//connected
}
}
//not connected
}
}
And based upon your requirement that you requires connected status only one time. First check for connectivity and if not connected then only register receiver.
public boolean isNetworkConnected() {
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
}
return false;
}
To access internet we need INTERNET Permission
To detect network status we need ACCESS_NETWORK_STATE Permission
Add these lines in your AndroidManifest.xml:
<!-- Internet Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Network State Permissions -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Create this method in your java class:
public boolean isConnectingToInternet(){
ConnectivityManager connectivity = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
return false;
}
When ever you want to check Internet Status in your application call isConnectingToInternet() function and it will return true or false
ConnectionDetector cd = new ConnectionDetector(getApplicationContext());
Boolean isInternetPresent = cd.isConnectingToInternet(); // true or false

Android: connecting to USB device, wait for permission

I'm trying to do this: connect to USB device and get the opened (or failed) connection. I did the logic according to examples and explanations that I have found, but I have problem with waiting for permission grant. First I tried a "good" way of using wait()+notifyAll(), than I tried straightforward loop with checks, but both times the waiting method (waitConnection()) was blocking for the timeout I gave it, and only after that the message was received. So I tried these 2 versions.
wait/notifyAll:
public UsbConnector startConnection(Context context) {
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (syncObj) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
if (device.getVendorId() == vendorId && device.getProductId() == productId) {
connection = usbManager.openDevice(device);
connectedDevice = device;
}
}
}
syncObj.notyfyAll();
}
}
}
};
try {
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (final UsbDevice device : usbManager.getDeviceList().values()) {
if (device.getVendorId() == this.vendorId && device.getProductId() == this.productId) {
context.registerReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION));
usbManager.requestPermission(device,
PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0));
break;
}
}
} catch (Exception e) {
}
return this;
}
public UsbDeviceConnection waitConnection(int timeout) {
try {
Thread.sleep(10, 0);
syncObj.wait(timeout);
} catch (InterruptedException e) {
}
return getConnection();
}
straightforward loop
public UsbConnector startConnection(Context context) {
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (device != null) {
if (device.getVendorId() == vendorId && device.getProductId() == productId) {
connection = usbManager.openDevice(device);
connectedDevice = device;
}
}
}
permissionRequested = false;
}
}
}
};
try {
permissionRequested = false;
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
for (final UsbDevice device : usbManager.getDeviceList().values()) {
if (device.getVendorId() == this.vendorId && device.getProductId() == this.productId) {
permissionRequested = true;
context.registerReceiver(receiver, new IntentFilter(ACTION_USB_PERMISSION));
usbManager.requestPermission(device,
PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0));
break;
}
}
} catch (Exception e) {
}
return this;
}
public UsbDeviceConnection waitConnection(int timeout) {
int waited = timeout;
while (permissionRequested && waited > 0) {
try {
Thread.sleep(10, 0);
} catch (InterruptedException e) {
}
waited -= 10;
}
return getConnection();
}
So in both cases, according to logs, the waitConnection() method (that is called by the consumer immediately after startConnection()) seems to block the execution (I gave it timeout 10 seconds, and it was blocked for 10 seconds), and only right after it's completed, the BroadcastReceiver gets the message. It appears that requestPermission() is not async (as I thought it is), but in this case, how is it possible that startConnection() exits immediately and before the message is received? And how can I wait for BroadcastReceiver to get the message? Say if I don't use the waitConnection() method, how my consumer should know the moment when it can start checking for connection availability?
"and only right after it's completed, the BroadcastReceiver gets the message"
The onReceived callback, by default, is called on the main thread. It sounds like you are calling waitConnection() on the main thread as well. Since waitConnection() blocks, the main thread cannot process any additional messages until waitConnection() returns. This means that onReceived will not be called until waitConnection() times out.
It is generally a bad idea to block the main thread. Read here
Instead, you could have onReceive launch a new activity which then does whatever it is you need to do once you get USB permission. That may or may not be the best solution for you, but regardless, the key here is to never block the main thread.

Categories

Resources