WIFI経由のネットワーク接続があることを検出する必要があります。有効なネットワーク接続が確立されたことを確立するために送信されるブロードキャスト。HTTPの有効なネットワーク接続が存在することを確認する必要があります。有効な接続が存在することを確認するために何をリッスンし、どの追加テストを行う必要がありますか。
WIFI経由のネットワーク接続があることを検出する必要があります。有効なネットワーク接続が確立されたことを確立するために送信されるブロードキャスト。HTTPの有効なネットワーク接続が存在することを確認する必要があります。有効な接続が存在することを確認するために何をリッスンし、どの追加テストを行う必要がありますか。
回答:
BroadcastReceiver
WiFi接続が確立された場合(または接続が変更された場合)に通知を受け取るように登録できます。
登録BroadcastReceiver
:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
そして、あなたの中BroadcastReceiver
で次のようなことをしてください:
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false)) {
//do stuff
} else {
// wifi connection was lost
}
}
}
詳細については、BroadcastReceiver
およびのドキュメントを参照してくださいWifiManager
もちろん、この前にデバイスがすでにWiFiに接続されているかどうかを確認する必要があります。
編集:ban-geoengineeringのおかげで、デバイスがすでに接続されているかどうかを確認する方法は次のとおりです:
private boolean isConnectedViaWifi() {
ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return mWifi.isConnected();
}
private boolean isConnectedViaWifi() { ConnectivityManager connectivityManager = (ConnectivityManager) appObj.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); return mWifi.isConnected(); }
私のために働いた最高のもの:
<receiver android:name="com.AEDesign.communication.WifiReceiver" >
<intent-filter android:priority="100">
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if(info != null && info.isConnected()) {
// Do your work.
// e.g. To check the Network Name or other info:
WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
}
}
}
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
私にとってはWifiManager.NETWORK_STATE_CHANGED_ACTION
機能します。
放送受信機を登録します。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
そして受け取る:
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if(action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)){
NetworkInfo info = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean connected = info.isConnected();
//call your method
}
}
ユーザー@JPMと@usmanによる回答は非常に便利です。それは正常に動作しますが、私の場合、それonReceive
は私の場合には4回複数回来るので、私のコードは複数回実行されます。
私はいくつかの変更を行い、私の要件に従って作成しましたが、今では1回しかありません
これがBroadcastのJavaクラスです。
public class WifiReceiver extends BroadcastReceiver {
String TAG = getClass().getSimpleName();
private Context mContext;
@Override
public void onReceive(Context context, Intent intent) {
mContext = context;
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI &&
networkInfo.isConnected()) {
// Wifi is connected
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
String ssid = wifiInfo.getSSID();
Log.e(TAG, " -- Wifi connected --- " + " SSID " + ssid );
}
}
else if (intent.getAction().equalsIgnoreCase(WifiManager.WIFI_STATE_CHANGED_ACTION))
{
int wifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
if (wifiState == WifiManager.WIFI_STATE_DISABLED)
{
Log.e(TAG, " ----- Wifi Disconnected ----- ");
}
}
}
}
AndroidManifest内
<receiver android:name=".util.WifiReceiver" android:enabled="true">
<intent-filter>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
あなたはできますが、ユーザーを毎回尋ねるの正常な動作をオーバーライドする選択肢を与える場合は無線LAN接続を開始します。
私は3つの方法を使用することを選択します...
public boolean isOnline()
{
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
これは、WifiまたはCellDataのいずれかにインターネット接続があるかどうかをすばやく確認するためのものです。ここから、実行するアクションを選択できます。機内モードかどうかも確認する必要があります。
別のスレッド。変数IpAddressを= ""に設定し、有効なIPアドレスが得られるまでポーリングします。
WifiManager wifi;
wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifi.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ip = null;
ip = String.format("%d.%d.%d.%d",
(ipAddress & 0xff),
(ipAddress >> 8 & 0xff),
(ipAddress >> 16 & 0xff),
(ipAddress >> 24 & 0xff));
Log.e(" >>IP number Begin ",ip);
別のコードスニペット...オンになっていない場合はオンにします(ユーザーの事前の許可を得て)
if(wifi.isWifiEnabled()!=true)wifi.setWifiEnabled(true);
WIFI接続状態を検出するために、ConnectivityManagerクラスのCONNECTIVITY_ACTIONを使用しました。
IntentFilter filter=new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(receiver, filter);
BroadCastReceiverから:
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
int networkType = intent.getIntExtra(
android.net.ConnectivityManager.EXTRA_NETWORK_TYPE, -1);
if (ConnectivityManager.TYPE_WIFI == networkType) {
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (networkInfo != null) {
if (networkInfo.isConnected()) {
// TODO: wifi is connected
} else {
// TODO: wifi is not connected
}
}
}
}
ps:私にとってはうまくいきます:)
このコードはまったく許可を必要としません。Wi-Fiネットワーク接続状態の変更のみに制限されます(他のネットワークは考慮されません)。受信機は、静的にAndroidManifest.xmlファイルに公開され、それがシステムによって呼び出されるようにエクスポートする必要はありませんprotected broadcast
、NETWORK_STATE_CHANGED_ACTION
すべてのネットワーク接続状態の変更で、。
AndroidManifest:
<receiver
android:name=".WifiReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<!--protected-broadcast: Special broadcast that only the system can send-->
<!--Corresponds to: android.net.wifi.WifiManager.NETWORK_STATE_CHANGED_ACTION-->
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
BroadcastReceiverクラス:
public class WifiReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
/*
Tested (I didn't test with the WPS "Wi-Fi Protected Setup" standard):
In API15 (ICE_CREAM_SANDWICH) this method is called when the new Wi-Fi network state is:
DISCONNECTED, OBTAINING_IPADDR, CONNECTED or SCANNING
In API19 (KITKAT) this method is called when the new Wi-Fi network state is:
DISCONNECTED (twice), OBTAINING_IPADDR, VERIFYING_POOR_LINK, CAPTIVE_PORTAL_CHECK
or CONNECTED
(Those states can be obtained as NetworkInfo.DetailedState objects by calling
the NetworkInfo object method: "networkInfo.getDetailedState()")
*/
/*
* NetworkInfo object associated with the Wi-Fi network.
* It won't be null when "android.net.wifi.STATE_CHANGE" action intent arrives.
*/
NetworkInfo networkInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
if (networkInfo != null && networkInfo.isConnected()) {
// TODO: Place the work here, like retrieving the access point's SSID
/*
* WifiInfo object giving information about the access point we are connected to.
* It shouldn't be null when the new Wi-Fi network state is CONNECTED, but it got
* null sometimes when connecting to a "virtualized Wi-Fi router" in API15.
*/
WifiInfo wifiInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
String ssid = wifiInfo.getSSID();
}
}
}
権限:
None
これは、Wifiに接続したときに通信のみを許可するというユーザー設定を考慮した私のコードの例です。
私はIntentService
ものをダウンロードしようとする前に内部からこのコードを呼び出しています。
注NetworkInfo
だろうnull
いかなる種類のネットワーク接続が存在しない場合。
private boolean canConnect()
{
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
boolean canConnect = false;
boolean wifiOnly = SharedPreferencesUtils.wifiOnly();
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo != null)
{
if(networkInfo.isConnected())
{
if((networkInfo.getType() == ConnectivityManager.TYPE_WIFI) ||
(networkInfo.getType() != ConnectivityManager.TYPE_WIFI && !wifiOnly))
{
canConnect = true;
}
}
}
return canConnect;
}
Android Oは、wifiの状態変更の暗黙的なブロードキャストを受信する可能性を削除しました。そのため、アプリが閉じていると、それらを受け取ることができません。新しいものWorkManager
は、アプリが閉じられたときに実行する機能を備えているため、少し試してみたところ、非常にうまく機能しているようです。
これを依存関係に追加します。
implementation "android.arch.work:work-runtime:1.0.0-alpha08"
WifiConnectWorker.kt
class WifiConnectWorker : Worker() {
override fun doWork(): Result {
Log.i(TAG, "I think we connected to a wifi")
return Result.SUCCESS
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
val workManager = WorkManager.getInstance()
// Add constraint to start the worker when connecting to WiFi
val request = OneTimeWorkRequest.Builder(WifiConnectWorker::class.java)
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(UNMETERED)
.build())
.build()
// The worker should be started, even if your app is closed
workManager.beginUniqueWork("watch_wifi", REPLACE, request).enqueue()
}
}
これは1回限りの通知の簡単なテストでした。WiFiがオン/オフになったときに常に通知を受け取るには、さらに多くの作業が必要です。
PS:アプリが強制終了されると、ワーカーは起動せずWorkManager
、リクエストをキャンセルしているようです。
私はこのコードを使用しました:
public class MainActivity extends Activity
{
.
.
.
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
.
.
.
}
@Override
protected void onResume()
{
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
registerReceiver(broadcastReceiver, intentFilter);
}
@Override
protected void onPause()
{
super.onPause();
unregisterReceiver(broadcastReceiver);
}
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION))
{
if (intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false))
{
// wifi is enabled
}
else
{
// wifi is disabled
}
}
}
};
}
アプリケーションコンテキストを受信するWIFI接続を検出するには、2つの方法があります。
public boolean isConnectedWifi1(Context context) {
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if (networkInfo != null) {
NetworkInfo[] netInfo = connectivityManager.getAllNetworkInfo();
for (NetworkInfo ni : netInfo) {
if ((ni.getTypeName().equalsIgnoreCase("WIFI"))
&& ni.isConnected()) {
return true;
}
}
}
return false;
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
return false;
}
public boolean isConnectedWifi(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
return networkInfo.isConnected();
}
CONNECTIVITY_CHANGEブロードキャストを楽しんでいるすべての人にとって、アプリがAndroid Oでバックグラウンドにある場合、これは発生しなくなりました。
https://developer.android.com/about/versions/o/background.html
1)CONNECTIVITY_ACTION / CONNECTIVITY_CHANGEがAPI 28で廃止され、推奨されていないことを知っていても、ブロードキャストレシーバーアプローチを試しました。また、明示的なレジスタの使用にバインドされており、アプリが実行されている限り待機します。
2)Firebase Dispatcherも試しましたが、機能しますが、アプリが強制終了されません。
3)推奨される方法として、WorkManagerが見つかり、プロセスが強制終了され、内部でregisterNetworkRequest()を使用して実行されることが保証されます。
#3アプローチを支持する最大の証拠は、Androidドキュメント自体によって参照されます。特にバックグラウンドのアプリの場合。
また、ここでは
Android 7.0では、一般的に使用される3つの暗黙的なブロードキャスト(CONNECTIVITY_ACTION、ACTION_NEW_PICTURE、ACTION_NEW_VIDEO)を削除しています。これらは、複数のアプリのバックグラウンドプロセスを一度に起動し、メモリとバッテリーに負担をかける可能性があるためです。アプリがこれらを受信している場合は、Android 7.0を利用して、代わりにJobSchedulerおよび関連するAPIに移行してください。
これまでのところ、Periodic WorkManagerリクエストを使用すると問題なく動作します。
更新:私はそれについて2シリーズのミディアムポストを書いてしまいました。