可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there an Android Intent ACTION_XXX
that notifies me when an Internet Connection is available?
I want to instantiate a BroadcastReceiver
that notifies my application when a user enables Internet Connection (by wifi, by GSM, etc.)
Could anyone help me?
回答1:
<receiver android:name=\".YOURRECEIVER\">
<intent-filter>
<action android:name=\"android.net.conn.CONNECTIVITY_CHANGE\" />
</intent-filter>
</receiver>
<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />
回答2:
Accepted answer is correct. I only add Receiver code for completion:
public class NetworkStateReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Log.d(\"app\",\"Network connectivity change\");
if(intent.getExtras()!=null) {
NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
Log.i(\"app\",\"Network \"+ni.getTypeName()+\" connected\");
} else if(intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
Log.d(\"app\",\"There\'s no network connectivity\");
}
}
}
回答3:
Update to @lujop answer:
public class NetworkStateReceiver extends BroadcastReceiver {
private static final String TAG = \"NetworkStateReceiver\";
@Override
public void onReceive(final Context context, final Intent intent) {
Log.d(TAG, \"Network connectivity change\");
if (intent.getExtras() != null) {
final ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo ni = connectivityManager.getActiveNetworkInfo();
if (ni != null && ni.isConnectedOrConnecting()) {
Log.i(TAG, \"Network \" + ni.getTypeName() + \" connected\");
} else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
Log.d(TAG, \"There\'s no network connectivity\");
}
}
}
}
回答4:
MyReceiver.java
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if(isConnected(context)) Toast.makeText(context, \"Connected.\", Toast.LENGTH_LONG).show();
else Toast.makeText(context, \"Lost connect.\", Toast.LENGTH_LONG).show();
}
public boolean isConnected(Context context) {
ConnectivityManager cm =
(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null &&
activeNetwork.isConnected();
return isConnected;
}
}
AndroidManifest.xml
<uses-permission android:name=\"android.permission.INTERNET\" />
<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />
UPDATE
If your app targets API level 26 or higher, you cannot use the
manifest to declare a receiver for implicit broadcasts (broadcasts
that do not target your app specifically), except for a few implicit
broadcasts that are exempted from that restriction. In most cases, you
can use scheduled jobs instead.
usage
connection = MyReceiver()
// onCreate - onDestroy, onResume - onPause depends on you
override fun onStart() {
super.onStart()
registerReceiver(connection, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}
override fun onStop() {
super.onStop()
// remember unregister to avoid leak
unregisterReceiver(connection)
}
UPDATE 2
CONNECTIVITY_ACTION
This constant was deprecated in API level 28.
apps should use the more versatile requestNetwork(NetworkRequest, PendingIntent)
, registerNetworkCallback(NetworkRequest, PendingIntent)
or registerDefaultNetworkCallback(ConnectivityManager.NetworkCallback)
functions instead for faster and more detailed updates about the network changes they care about.
because it added in API level 22
, so above code will work fine on all versions of android
回答5:
The missing part of all answers is a reminder to register for that action:
IntentFilter filter = new IntentFilter();
filter.addAction(\"android.net.conn.CONNECTIVITY_CHANGE\");
registerReceiver(your_receiver, filter);
回答6:
I\'m using broadcast to check the connection every time. Create a class for connection info.
import android.content.Context;
import android.content.ContextWrapper;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class ConnectivityStatus extends ContextWrapper{
public ConnectivityStatus(Context base) {
super(base);
}
public static boolean isConnected(Context context){
ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo connection = manager.getActiveNetworkInfo();
if (connection != null && connection.isConnectedOrConnecting()){
return true;
}
return false;
}
}
Apply code into your Activity:
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(!ConnectivityStatus.isConnected(getContext())){
// no connection
}else {
// connected
}
}
};
Register broadcast in your activity\'s onCreate()
method:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
your_activity_context.registerReceiver(receiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
..
...
....
}
Don\'t forget to unregistered/register on Activity cycle:
@Override
protected void onResume() {
super.onResume();
your_activity_context.registerReceiver(receiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
@Override
protected void onPause() {
super.onPause();
your_activity_context.unregisterReceiver(receiver);
}
回答7:
This code will work (in all versions) as the manifest registration will not work for 7+(API 25 and above) devices see this link.
private void foo(){
registerReceiver(connectionBroadcastReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
private BroadcastReceiver connectionBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null || intent.getExtras() == null)
return;
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.getState() == NetworkInfo.State.CONNECTED) {
// connected
}
}
};
回答8:
Continuing meow mwo\'s Answer
you can enable/disable the receiver by:
enable
ComponentName receiver = new ComponentName(MainActivity.this, MyReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
Toast.makeText(this, \"Disabled broadcst receiver\", Toast.LENGTH_SHORT).show();
}
disable
ComponentName receiver = new ComponentName(MainActivity.this, MyReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
Toast.makeText(this, \"Enabled broadcast receiver\", Toast.LENGTH_SHORT).show();
}
where, the same can be called in an Intent or in onCreate
回答9:
NetworkInfo.isConnected()
is unreliable method to test for internet status, it will return true when there is a network connection even though it may have no internet access (ex. wifi with no internet). A more reliable approach would be to use ping
with a CONNECTIVITY_ACTION
BroadcastReceiver
:
private void registerInternetReceiver()
{
if (this.internetReceiver != null) return;
this.internetReceiver = new BroadcastReceiver()
{
@Override
public void onReceive (Context context, Intent intent)
{
if (isInternetAvailable()) Log.i (\"Tag\", \"internet status online\");
else Log.i (\"Tag\", \"internet status offline\");
}
};
IntentFilter filter = new IntentFilter();
filter.addAction (ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver (internetReceiver, filter);
}
private boolean isInternetAvailable()
{
try
{
return (Runtime.getRuntime().exec (\"ping -c 1 google.com\").waitFor() == 0);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return false;
}
回答10:
**Also worked on above Android 7.0**
// AndroidManifest.xml
<service
android:name=\".NetworkSchedulerService\"
android:exported=\"true\"
android:permission=\"android.permission.BIND_JOB_SERVICE\"/>
// MyApplication.java
import android.app.Application;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
public class MyApplication extends Application {
private static Context context;
public static Context getContext() {
return context;
}
public static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication mInstance;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
mInstance = this;
scheduleJob();
}
public static synchronized MyApplication getInstance() {
return mInstance;
}
private void scheduleJob()
{
JobInfo myJob = new JobInfo.Builder(0, new ComponentName(this, NetworkSchedulerService.class))
.setRequiresCharging(true)
.setMinimumLatency(1000)
.setOverrideDeadline(2000)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setPersisted(true)
.build();
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
assert jobScheduler != null;
jobScheduler.schedule(myJob);
}
}
// Constants.java
public class Constants {
public static final String CONNECT_TO_WIFI = \"WIFI\";
public static final String CONNECT_TO_MOBILE = \"MOBILE\";
public static final String NOT_CONNECT = \"NOT_CONNECT\";
public final static String CONNECTIVITY_ACTION = \"android.net.conn.CONNECTIVITY_CHANGE\";
}
// LiveConnectivityReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
public class LiveConnectivityReceiver extends BroadcastReceiver {
private MConnectivityReceiver mConnectivityReceiver;
LiveConnectivityReceiver(MConnectivityReceiver listener) {
mConnectivityReceiver = listener;
}
@Override
public void onReceive(Context context, Intent intent) {
mConnectivityReceiver.onNetworkConnectionChanged(isConnected(context));
}
public static boolean isConnected(Context context) {
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert cm != null;
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}
public interface MConnectivityReceiver {
void onNetworkConnectionChanged(boolean isConnected);
}
}
// MainActivity.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private BroadcastReceiver mReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStop() {
stopService(new Intent(this, NetworkSchedulerService.class));
super.onStop();
}
@Override
protected void onStart() {
super.onStart();
startService( new Intent(this, NetworkSchedulerService.class));
}
@Override
protected void onPause() {
super.onPause();
this.unregisterReceiver(this.mReceiver);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter(\"android.intent.action.MAIN\");
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean isConnection = intent.getBooleanExtra(\"VALUE\", false);
if (!isConnection) {
Toast.makeText(context, \"No Internet Connection\", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, \"Back to online\", Toast.LENGTH_SHORT).show();
}
}
};
this.registerReceiver(mReceiver, intentFilter);
}
}
// NetworkSchedulerService.java
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Intent;
import android.content.IntentFilter;
public class NetworkSchedulerService extends JobService implements LiveConnectivityReceiver.ConnectivityReceiverListener
{
private LiveConnectivityReceiver mLiveConnectivityReceiver;
@Override
public void onCreate()
{
super.onCreate();
mLiveConnectivityReceiver = new LiveConnectivityReceiver(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
@Override
public boolean onStartJob(JobParameters params) {
registerReceiver(mLiveConnectivityReceiver, new IntentFilter(Constants.CONNECTIVITY_ACTION));
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
unregisterReceiver(mLiveConnectivityReceiver);
return true;
}
@Override
public void onNetworkConnectionChanged(boolean isConnected)
{
Intent broadcastedIntent=new Intent(\"android.intent.action.MAIN\");
broadcastedIntent.putExtra(\"VALUE\", isConnected);
sendBroadcast(broadcastedIntent);
}
}
回答11:
I would read the docs updated for nougat + , because intent is deprecated due to the # of devices, network info alone is not sufficient. I would use connectivity manager ( connectivity action, add variables there) commands and vars there, because most has changed in the last year alone, and on for testing, enable cell data always active, verbose logging and aggressive handover, use wlan filter if needed:
https://developer.android.com/reference/android/net/ConnectivityManager.html#CONNECTIVITY_ACTION
回答12:
From Android 7++, @fedj\'s answer will not work but you can register the broadcast receiver programmatically.
Apps targeting Android 7.0 (API level 24) and higher do not receive
CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver
in their manifest. Apps will still receive CONNECTIVITY_ACTION
broadcasts if they register their BroadcastReceiver with
Context.registerReceiver() and that context is still valid.