问题
Nougat changed the way it handles CONNECTIVITY_CHANGED intents (basically ignoring it, forcing devs to use the job scheduler) so this leaves me wondering:
If I have an app that is in the middle of retrieving some data (and I checked if the phone was online at the time I did the request but the user is on the move and the phone connects to a different wifi access point, for example) and it fails, how do I detect that the connection has been restored and I cam retry fetxhing the data?
So in this case my app is in the foreground, I think Chrome (for android) has a similar function.
Do I need to poll it myself? Or is there some event that is allowed at that time?
回答1:
Apps that are running can still listen for CONNECTIVITY_CHANGE
on their main thread if they request notification with a BroadcastReceiver.
https://developer.android.com/about/versions/nougat/android-7.0-changes.html
回答2:
While Andromeda's answer could be used, that solution is not Google's intended choice. Your question was what to do when a connection is lost and you need to resume operation when network service returns.
While CONNECTIVITY_CHANGE technically works, it was always a bit of a hack for this specific need and it will stop working in Nougat as soon as your app goes in the background. What you should really use is a job scheduler API. Google has offered us many options with differing requirements and features.
- JobScheduler
JobScheduler was added in Lollipop and adds a scheduler which can wait for network connectivity to schedule a job. It can even depend on the kind of connection, checking for unmetered or non-roaming connections. This option has no backwards compatibility, but works without Google Play Services.
- GCM Network Manager
GcmNetworkManager is a direct port of the JobScheduler functionality to versions before Lollipop, but it requires Google Play Services. GcmNetworkManager has been mostly deprecated by Firebase Job Dispatcher.
- Firebase Job Dispatcher
Firebase JobDispatcher provides another means to schedule jobs for versions before Lollipop, which uses Google Play Services by default, but can be configured to not require this dependency.
- WorkManager
I just edited this post to add that Google replaced all of the three previous job schedulers by WorkManager, which is better than the others in almost every way. You can set a required network type for your job to run. You can even chain jobs together one after another.
All of these options will satisfy your need in a battery-friendly manner and your jobs will still get scheduled even if the device wakes up briefly from Doze mode.
Here is more information about the various options with examples provided by Google:
https://developer.android.com/topic/performance/scheduling.html https://developer.android.com/topic/performance/background-optimization.html#sched-jobs
回答3:
According to doc:
Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION
broadcasts if they declare their broadcast receiver in the manifest. Apps will still receive CONNECTIVITY_ACTION
broadcasts if they register their BroadcastReceiver
with Context.registerReceiver()
and that context is still valid.
回答4:
In my case I've subscribed to broadcast with CONNECTIVITY_CHANGE
filter in Service and it's working.
How to keep Service
alive is another story :)
回答5:
public class ConnectivityReceiver
{
public static boolean getWifiStatus(Context context)
{
// To get System Connectivity status
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (null != activeNetwork)
{
// Check For Wifi Status
if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
return true;
else
return false;
}
return false;
}
public class NetworkMgr extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityReceiver cf = new ConnectivityReceiver();
boolean status = cf.getWifiStatus(context);
if(status)
{
Toast.makeText(context,"Wifi Connection is On.", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(context,"Wifi Connection is Off.", Toast.LENGTH_SHORT).show();
}
}
}
来源:https://stackoverflow.com/questions/39210191/detect-connectivity-changes-on-android-7-0-nougat-when-app-is-in-foreground