Skip to content Skip to sidebar Skip to footer

Action_pick_wifi_network On A Dialog With Avaliable Networks

I'm trying to create a Dialog which shows something like ACTION_PICK_WIFI_NETWORK but instead of open Android Settings / WiFi open it on a Dialog and if it's possible user could co

Solution 1:

From the ui perspective you need a Custom adapter:

privateclassWifiAdapterextendsArrayAdapter<ScanResult> {

    publicWifiAdapter(Context context, int resource, List<ScanResult> objects) {
        super(context, resource, objects);
    }

    @Overridepublic View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = getLayoutInflater().inflate(R.layout.wifi_item, parent, false);
        }
        ScanResultresult= getItem(position);
        ((TextView) convertView.findViewById(R.id.wifi_name)).setText(formatSSDI(result));
        ((ImageView) convertView.findViewById(R.id.wifi_img)).setImageLevel(getNormalizedLevel(result));
        return convertView;
    }

    privateintgetNormalizedLevel(ScanResult r) {
        intlevel= WifiManager.calculateSignalLevel(r.level,
                5);
        Log.e(getClass().getSimpleName(), "level " + level);
        return level;
    }

    private String formatSSDI(ScanResult r) {
        if (r == null || r.SSID == null || "".equalsIgnoreCase(r.SSID.trim())) {
            return"no data";
        }
        return r.SSID.replace("\"", "");
    }

I slightly changed your showWifiListDialog:

privatevoidshowWifiListDialog(List<ScanResult> results) {
    Collections.sort(results, newComparator<ScanResult>() {
        @Overridepublicintcompare(ScanResult lhs, ScanResult rhs) {
            return rhs.level > lhs.level ? 1 : rhs.level < lhs.level ? -1 : 0;
        }
    });
    AlertDialog.BuilderbuilderSingle=newAlertDialog.Builder(
            this);
    finalWifiAdapterarrayAdapter=newWifiAdapter(
            this,
            android.R.layout.select_dialog_item, results);

    builderSingle.setNegativeButton(getString(android.R.string.cancel),
            newDialogInterface.OnClickListener() {
                @OverridepublicvoidonClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    builderSingle.setAdapter(arrayAdapter,
            newDialogInterface.OnClickListener() {
                @OverridepublicvoidonClick(DialogInterface dialog, int which) {
                    StringstrName= arrayAdapter.getItem(which).SSID;
                    Toast.makeText(getApplicationContext(), "Selected " + strName, Toast.LENGTH_SHORT).show();
                }
            });
    AlertDialogdialog= builderSingle.create();
    dialog.show();
}

the Wifi Item is

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><TextViewandroid:textSize="16sp"android:padding="5dp"android:layout_gravity="center_vertical"android:id="@+id/wifi_name"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1" /><ImageViewandroid:id="@+id/wifi_img"android:layout_gravity="center_vertical"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@drawable/wifi_level" /></LinearLayout>

and the drawable wifi_level is

<?xml version="1.0" encoding="utf-8"?><level-listxmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:drawable="@drawable/ic_signal_wifi_0_bar_black_24dp"android:maxLevel="0" /><itemandroid:drawable="@drawable/ic_signal_wifi_1_bar_black_24dp"android:maxLevel="1" /><itemandroid:drawable="@drawable/ic_signal_wifi_2_bar_black_24dp"android:maxLevel="2" /><itemandroid:drawable="@drawable/ic_signal_wifi_3_bar_black_24dp"android:maxLevel="3" /><itemandroid:drawable="@drawable/ic_signal_wifi_4_bar_black_24dp"android:maxLevel="4" /></level-list>

I took the five png from here

For the Connection, the answer is yes it should be possible. Accordingly to the documentation at least. You can instantiate an object of WifiConfiguration, and feed it with info of the network you want to connect to (SSID and password). It is not a straightforward thing to do. If you have to take in consideration the different kind of keys encryption, (WPA, WEP, free wifi). Onceyou filled up the object, you have to call

mWifiManager.disconect();
int resId = mWifiManager.addNetwork(config);
mWifiManager.enableNetwork(resId, true);

Edit:

If you want to show the wifi-signal-strength icon with and without padlock, you could use custom attribute

<?xml version="1.0" encoding="utf-8"?><resources><declare-styleablename="wifi"><attrname="state_locked"format="boolean" /></declare-styleable></resources>

and update its state in a subclass of ImageView:

publicclassWifiImageViewextendsImageView {

privatestaticfinalint[] STATE_LOCKED = {R.attr.state_locked};
privateboolean mWifiLocked;

publicWifiImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

@Overridepublicint[] onCreateDrawableState(int extraSpace) {
    finalint[] drawableState = super.onCreateDrawableState(extraSpace + 1);
    if (mWifiLocked) {
        mergeDrawableStates(drawableState, STATE_LOCKED);
    }
    return drawableState;
}

publicvoidsetStateLocked(boolean locked) {
    mWifiLocked = locked;
    refreshDrawableState();
}

}

Now assuming that the android:src of your WifeImageView is a selector

<?xml version="1.0" encoding="utf-8"?><selectorxmlns:android="http://schemas.android.com/apk/res/android"xmlns:custom="http://schemas.android.com/apk/res-auto"><itemcustom:state_locked="false"android:drawable="@drawable/wifi_level" /><itemcustom:state_locked="true"android:drawable="@drawable/wifi_level_lock" /></selector>

In your Adapter you can easily switch between the two level-list, adding the following two lines of code

booleanprotectedWifi= result.capabilities.contains ("WEP") || result.capabilities.contains("WPA");
 ((WifiImageView) convertView.findViewById(R.id.wifi_img)).setStateLocked(protectedWifi);

protectedWifi is evaluated true if result.capabilities contains WEP or WPA, and setStateLocked(protectedWifi); will switch between the two level-lists accordingly to its value. Of course, in the wifi_item.xml, you have two change from ImageView, to the custom WifiImageView.

Solution 2:

I found the library WifiUtils to be extremely useful. To connect to a selected wifi network, create connectToWifi(ssid, pass)

privatefunconnectToWifi(ssid: String, password: String) {
    WifiUtils.withContext(applicationContext)
      .connectWith(ssid, password)
      .onConnectionResult(::connectWifiResultListener)
      .start()
}

Then, replace Toast.makeText(getApplicationContext(), "Selected " + strName, Toast.LENGTH_SHORT).show(); in showWifiListDialog setAdapter onClick with connectToWifi(strName, password)

The password can be empty "" if the wifi network doesn't require authentication

The result will return to connectWifiResultListener

privatefunconnectWifiResultListener(isSuccess: Boolean) {
    if (isSuccess)
      // do somethingelse}
      // show error
}

In addition, I adapted scanWifi from the WifiUtils library with @Skizo-ozᴉʞS wifi scanning solution and it worked like a charm. So, instead of the startWifiScans method and the wifiReceiver which calls showWifiListDialog(results) I used

WifiUtils.withContext(applicationContext).scanWifi(::getScanResults).start()

And call showWifiListDialog in getScanResults

privatefungetScanResults(results: List<ScanResult>) {
    if (results.isEmpty()) { return }
    showWifiListDialog(results)
  }

Post a Comment for "Action_pick_wifi_network On A Dialog With Avaliable Networks"