【问题标题】:ACTION_PICK_WIFI_NETWORK on a dialog with avaliable networksACTION_PICK_WIFI_NETWORK 与可用网络的对话框
【发布时间】:2015-07-01 13:16:46
【问题描述】:

我正在尝试创建一个Dialog,它显示类似ACTION_PICK_WIFI_NETWORK 的内容,但不是打开Android Settings / WiFi,而是在Dialog 上打开它,如果可能,用户可以连接到该Dialog 可用的任何网络.我目前正在打开一个Dialog 和一个List 在Android 中可用的Wi-Fi 网络,但是这个ListAndroid Settings / WiFi 不同,这就是为什么我要问它是否可能在对话框中打开此ACTION_PICK_WIFI_NETWORK 并使用它。如果不可能,我怎么能连接到网络,点击我的Dialog 中的Item 并提供 WiFi?

到目前为止我尝试过的是

我有一个BroadcastReceiver()

wifiReceiver = new BroadcastReceiver(){
@Override
  public void onReceive(Context c, Intent intent){  
       if(mWifiManager != null) {
          List<ScanResult> results = mWifiManager.getScanResults();
          showWifiListDialog(results);
       }
  }
};

RegisterReceiver()

registerReceiver(wifiReceiver,new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));

这是执行WifiScan的方法

private void startWifiScans() {
 mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
 mWifiManager.startScan();
}

这是简单的Dialog,它显示SCAN_RESULTS_AVAILABLE_ACTION

private void showWifiListDialog(List<ScanResult> results) {
    AlertDialog.Builder builderSingle = new AlertDialog.Builder(
            this);
    final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
            this,
            android.R.layout.select_dialog_item);

    for (ScanResult r: results) {
        if(r == null || r.SSID == null) continue;
        if("".equalsIgnoreCase(r.SSID.trim())) continue;
        String name = r.SSID.replace("\"", "");
        arrayAdapter.add(name);
    }
    builderSingle.setNegativeButton(getString(R.string.cancel),
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    builderSingle.setAdapter(arrayAdapter,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String strName = arrayAdapter.getItem(which);
                    Toast.makeText(getApplicationContext(),"Selected "+strName, Toast.LENGTH_SHORT).show();
                }
            });
    AlertDialog dialog = builderSingle.create();
    dialog.show();
}

图片示例

Thisthis 是示例或我正在寻找的内容。

编辑(这就是我现在看到我的Dialog,但我还不喜欢它......)

我想展示带有icon 的网络,其信号强度类似于android 的example。我想我需要一个 ListAdapter 左右?然后添加网络名称、强度连接、图标等...我错了吗?

几乎是同一个问题there..

我想通过Notification 打开它,显然我是在那个 APP 还是其他 APP 上都没关系...我只想将它作为一个对话框打开,让用户看看用户正在观看。

现在我得到的是:

我正在使用Theme,但它并没有达到我想要的效果。

<style name="dialogtest" parent="AppTheme">
    <item name="android:windowFrame">@android:color/transparent</item>
    <item name="android:windowIsFloating">true</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowBackground">@android:color/transparent</item>
</style>

这就是风格,我称之为这样做:

 protected void onCreate(Bundle savedInstanceState) {
    setTheme(R.style.dialogtest);
    super.onCreate(savedInstanceState);

【问题讨论】:

  • 我会对此进行调查并回复您。我以前没有这样做过...... :)
  • 好的,我已经编辑了我的答案并解释了更多。
  • 抱歉耽搁了。我一直忙于工作...... :(我理解你的问题。
  • 到目前为止,我还无法弄清楚这是如何做到的......
  • 没关系...我想我会放一个赏金来看看aomeone是否可以帮助我:)

标签: android


【解决方案1】:

从用户界面的角度来看,您需要一个自定义适配器:

private class WifiAdapter extends ArrayAdapter<ScanResult> {

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

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

    private int getNormalizedLevel(ScanResult r) {
        int level = 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("\"", "");
    }

我稍微改变了你的showWifiListDialog

private void showWifiListDialog(List<ScanResult> results) {
    Collections.sort(results, new Comparator<ScanResult>() {
        @Override
        public int compare(ScanResult lhs, ScanResult rhs) {
            return rhs.level > lhs.level ? 1 : rhs.level < lhs.level ? -1 : 0;
        }
    });
    AlertDialog.Builder builderSingle = new AlertDialog.Builder(
            this);
    final WifiAdapter arrayAdapter = new WifiAdapter(
            this,
            android.R.layout.select_dialog_item, results);

    builderSingle.setNegativeButton(getString(android.R.string.cancel),
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    builderSingle.setAdapter(arrayAdapter,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    String strName = arrayAdapter.getItem(which).SSID;
                    Toast.makeText(getApplicationContext(), "Selected " + strName, Toast.LENGTH_SHORT).show();
                }
            });
    AlertDialog dialog = builderSingle.create();
    dialog.show();
}

Wifi 项目是

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android: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" />

    <ImageView
        android: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>

并且可绘制的wifi_level是

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

    <item
        android:drawable="@drawable/ic_signal_wifi_4_bar_black_24dp"
        android:maxLevel="4" />
</level-list>

我从here拿了五个png

对于连接,答案是是的,应该是可能的。至少根据文档。您可以实例化WifiConfiguration 的对象,并为其提供您要连接的网络的信息(SSIDpassword)。这不是一件简单的事情。如果您必须考虑不同类型的密钥加密,(WPAWEPfree wifi)。一旦你填满了对象,你必须调用

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

编辑:

如果您想显示带有和不带有挂锁的 wifi-signal-strength 图标,您可以使用自定义属性

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

并在 ImageView 的子类中更新其状态:

 public class WifiImageView extends ImageView {

private static final int[] STATE_LOCKED = {R.attr.state_locked};
private boolean mWifiLocked;

public WifiImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

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

public void setStateLocked(boolean locked) {
    mWifiLocked = locked;
    refreshDrawableState();
}

}

现在假设你的WifeImageView 的 android:src 是一个选择器

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

在你的Adapter中你可以很方便的在两个level-list之间切换,加入下面两行代码

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

如果result.capabilities 包含WEPWPA,则protectedWifi 被评估为真,并且setStateLocked(protectedWifi); 将根据其值在两个level-lists 之间切换。当然,在wifi_item.xml 中,您有两个从ImageView 到自定义WifiImageView 的更改。

【讨论】:

  • 为什么getLayoutInflater() 给我一个错误,说这是未定义的?
  • getLayoutInflater()Activity 的一个方法。根据用例,您可以传递上下文并使用 LayoutInflater.from(context) 或直接将 LayoutInflater 传递给适配器
  • 也许.. 我在清单中添加了&lt;activity android:name=".activities.TestActivity" android:theme="@style/dialogtest"&gt;,其中dialogtest 是您发布的内容。我只是把它的父级改为@android:style/Theme.Dialog,结果是here。唯一的区别是我没有使用通知来启动它
  • Sh*t... 我想通了... 我有 2 个活动... 1 当我有 openNotification()RemoveNotification() 等时...以及@987654361 的内部@ 我有 IntentDialog 活动....我已经更改了两个活动上的Theme...但我认为这不是最好的方法
  • 我把所有东西都放了here。如果您有任何疑问,请告诉我
【解决方案2】:

我发现库 WifiUtils 非常有用。要连接到选定的 wifi 网络,请创建 connectToWifi(ssid, pass)

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

然后,将showWifiListDialog setAdapter onClick 中的Toast.makeText(getApplicationContext(), "Selected " + strName, Toast.LENGTH_SHORT).show(); 替换为connectToWifi(strName, password)

如果wifi网络不需要认证,密码可以为空""

结果会返回connectWifiResultListener

 private fun connectWifiResultListener(isSuccess: Boolean) {
    if (isSuccess)
      // do something
    else}
      // show error
}

此外,我使用@Skizo-ozᴉʞS wifi 扫描解决方案改编了来自WifiUtils 库的scanWifi,它就像一个魅力。所以,我使用的不是startWifiScans 方法和调用showWifiListDialog(results)wifiReceiver

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

并在getScanResults 中调用showWifiListDialog

private fun getScanResults(results: List<ScanResult>) {
    if (results.isEmpty()) { return }
    showWifiListDialog(results)
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-04
    • 2011-03-11
    • 2023-03-19
    • 1970-01-01
    • 2015-10-24
    • 2021-12-28
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多