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に接続されているかどうかを確認する必要があります。
編集:禁止ジオエンジニアリングのおかげで、デバイスが既に接続されているかどうかを確認する方法があります:
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"/>
can毎回尋ねる通常の動作をオーバーライドする選択肢をユーザーに与えると、wifi接続を開始します。
私は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
Android Oは、Wi-Fi状態の変更に関する暗黙的なブロードキャストを受信する可能性を削除しました。したがって、アプリが閉じられている場合、それらを受信することはできません。新しい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:アプリがforce quitの場合、ワーカーは開始されておらず、WorkManager
がリクエストをキャンセルしているようです。
これは私のコードの例です。これは、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;
}
アプリケーションコンテキストを受信する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();
}
私はこのコードを使用しました:
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
}
}
}
};
}
CONNECTIVITY_CHANGEブロードキャストを楽しんでいるすべての人にとって、アプリがAndroid Oでバックグラウンドにある場合、これはもう発生しません。
https://developer.Android.com/about/versions/o/background.html
1) CONNECTIVITY_ACTION/CONNECTIVITY_CHANGE はAPI 28で非推奨であり、推奨されていませんが、ブロードキャストレシーバーアプローチも試しました。また、明示的なレジスタの使用にバインドされており、アプリが実行されている間はリッスンします。
2)Firebase Dispatcherも試してみました。FirebaseDispatcherは機能しますが、アプリが終了することはありません。
3)推奨される方法としては、WorkManagerを使用して、強制終了したプロセスを超えて内部で registerNetworkRequest() を使用して実行を保証します
#3アプローチを支持する最大の証拠は、 Android doc 自体によって参照されます。特にバックグラウンドのアプリの場合。
また、 ここ
Android 7.0では、一般的に使用される3つの暗黙的なブロードキャスト、CONNECTIVITY_ACTION、ACTION_NEW_PICTURE、およびACTION_NEW_VIDEOを削除します。これらは、複数のアプリのバックグラウンドプロセスを一度に起動し、メモリとバッテリーに負担をかけることができるためです。アプリがこれらを受け取っている場合は、Android 7.0を利用して、代わりにJobSchedulerおよび関連するAPIに移行してください。
これまでのところ、Periodic WorkManagerリクエストを使用することで問題なく動作します。