質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

0回答

4254閲覧

2回目の通信切り替えのリクエスト時、切り替えがうまくいっていない

rick

総合スコア18

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

1クリップ

投稿2019/05/21 22:17

編集2019/06/10 22:05

Wi-fi ONかつMobile ON状態で
使用する通信回線を切り替えるアプリを作成しています。

Wi-fi→Mobile, もしくはMobile→Wi-fiの通信切り替えのリクエストをしているのですが
2回目のリクエストが反映されず困っております。

対象はSDKバージョン 28で、リクエストにはConectivityManagerクラスを使用しております。
現象は以下となります。

モバイル通信リクエスト後、アプリ内Webviewでサイト閲覧Wi-fi通信リクエスト後、アプリ内Webviewでサイト閲覧
モバイル通信量通信量アップ(想定通り)通信量アップ(想定通りではない)
Wi-fi 通信量変化なし(想定通り)変化なし(想定通りではない)
Wi-fi通信リクエスト後、アプリ内Webviewでサイト閲覧モバイル通信リクエスト後、アプリ内Webviewでサイト閲覧
モバイル通信量変化なし(想定通り)変化なし(想定通りではない)
Wi-fi 通信量通信量アップ(想定通り)通信量アップ(想定通りではない)

       

通信リクエスト時は、onAvailable()の通知が来た際にbindProcessNetwork(network)を行い、
通信回線をバインドしております。
https://developer.android.com/reference/android/net/ConnectivityManager
「ConnectivityManager」
registerNetworkCallback(NetworkRequest request, ConnectivityManager.NetworkCallback networkCallback)
bindProcessToNetwork(Network network)

現象としては、1回目のリクエスト時の何かが残っているのではないかと疑ったのですが
2回目のリクエスト時に以下の終了処理をしているため、1回目のリクエストは残っていないはず・・と思っております。
・unregisterNetworkCallback (networkCallback) ←コールバック登録の解除
・networkCallback = null;            ←コールバックインスタンスをNull

AndroidはWi-fiとMobileが両方ONになっているときにWi-fiを優先するのは理解していますが
私のConectivityManagerの使い方が間違っているか、Android OSのせいなのか。

※ちなみにWi-fi通信のリクエスト(2回目のリクエスト)をした際、onAvailable()ではnetworkはWi-fiが返ってきており
bindProcessToNetwork()の戻り値はtrueとなっており、バインドはうまくいっているが
その後、モバイルに強制的に切り替わっているようです。

何か解決案がありましたら、先生方にご教授頂ければと思っております。よろしくお願い致します。

(2019/05/22 追記)
やりたい事としては、ファイルのDLのみモバイル通信で行うことです。

DownloadManagerクラスに、ファイルDLをする際、指定した通信でDLを許可するメソッドがあります。
こちらも試してみましたが、mobileのみを許可したのにwi-fi接続でDLをしており、うまく動いてくれませんでした。

(2019/06/11 追記)
MainActivity.java

private ConnectivityManager.NetworkCallback mCallback = null; @Override protected void onCreate(Bundle savedInstanceState) { button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String res = initCheck(); switch (res) { case "Wi-fi通信": // モバイル通信リクエスト networkChange(NetworkCapabilities.TRANSPORT_CELLULAR); break; case "モバイル通信": // Wi-fi通信リクエスト networkChange(NetworkCapabilities.TRANSPORT_WIFI); break; default: break; } init(); } private String initCheck() { ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); Network[] allNetwork = connectivityManager.getAllNetworks(); String res = null; for (Network network : allNetwork) { NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network); if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { // WiFi network res = "Wi-fi通信"; } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { // Mobile network res = "モバイル通信"; } else { // Other network res = "それ以外"; } } return res; private void init() { //request permissions int CODE_WRITE_SETTINGS_PERMISSION = 6789; boolean permission; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { permission = Settings.System.canWrite(this); } else { permission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_SETTINGS) == PackageManager.PERMISSION_GRANTED; } if (permission) { //Write allowed } else { //Write not allowed if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + this.getPackageName())); this.startActivityForResult(intent, CODE_WRITE_SETTINGS_PERMISSION); } else { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_SETTINGS}, CODE_WRITE_SETTINGS_PERMISSION); } } } private void networkChange(int request) { ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); // リクエストしたいNetworkを取得するためにNetworkRequestを作成 NetworkRequest.Builder builder = new NetworkRequest.Builder(); // Networkの種類を指定 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); // Transportタイプを指定 builder.addTransportType(request); NetworkRequest networkRequest = builder.build(); // ネットワークリセット resetDefaultNetwork(connectivityManager); try { Thread.sleep(1000); } catch (InterruptedException e) { } mCallback = new NetworkChangeCallback(connectivityManager); // NetworkRequestとNetworkCallbackを使ってNetworkをリクエストする connectivityManager.requestNetwork(networkRequest, mCallback); } private void resetDefaultNetwork(ConnectivityManager manager) { // すでにプロセスのネットワークが設定されている時はnullを設定する if (manager.getBoundNetworkForProcess() != null) { manager.bindProcessToNetwork(null); } // NetworkCallbackを設定している時はunregisterする if (mCallback != null) { try { manager.unregisterNetworkCallback(mCallback); mCallback = null; } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } } } /** * 通信リクエスト後のコールバッククラス */ private class NetworkChangeCallback extends ConnectivityManager.NetworkCallback { ConnectivityManager mManager = null; public NetworkChangeCallback(ConnectivityManager mConnectivityManager) { mManager = mConnectivityManager; } @Override public void onAvailable(Network network) { super.onAvailable(network); boolean result = mManager.bindProcessToNetwork(network); if (!result) { Log.e(TAG, "バインド失敗"); } else { checkNetwork(); } } ・・・ private void checkNetwork() { // 設定したいNetworkが使えるかは確認しておいていいと思います。 Network[] allNetwork = mManager.getAllNetworks(); Button button = findViewById(R.id.button_con_result); for (Network network : allNetwork) { NetworkCapabilities networkCapabilities = mManager.getNetworkCapabilities(network); if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { // WiFi network button.setText("Wi-fi通信"); } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { // Mobile network button.setText("モバイル通信"); } else { // Other network button.setText("それ以外"); } } } };

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" />

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2019/05/21 23:01

実行して現象を再現・確認出来る, 極力小さいコードを作成してご提示願えますか.
tmp

2019/06/10 12:04

知らない私が答えるのもなんですが、知りたいのでConectivityManagerの説明を読んでみました。 マルチコネクション対応になったので、setProcessDefaultNetworkから、bindProcessToNetworkに代わり、複数の経路を設定できるものだと思いますので それまでのバインドされた経路をクリアするために、bindProcessToNetworkで新たなネットワーク追加前に、bindProcessToNetwork(null);を追加してはどうでしょうか?
rick

2019/06/10 21:33

jimbe様 大変遅くなりましたが、コードを追加させて頂きました。 tmp様 bindProcessToNetworkで新たなネットワーク追加前に、それまでバインドした経路のクリアは実施しております。(コード内のresetDefaultNetwork()にて)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問