Android:WifiP2PManager如何将peerList添加到ListView

时间:2018-08-07 15:24:21

标签: java android wifip2p

简介

嘿,我正在尝试构建一个从主机接收数据的Wifi-Direct P2P客户端。在获取数据之前,我需要建立连接,并且主机应该是组所有者(go_intent = 15)。建立连接之前,我需要知道它是否是我要查找的设备。为了进行测试,我想显示我所在区域中处于发现模式的所有设备。这意味着我还必须将自己置于发现模式下,才能从其他设备中被发现。

到目前为止,我一打开电源开关,或者在电源开关打开时WiFi再次出现时,就以MainActivity.classstartFindPeers()中启动发现模式。

虽然开关处于打开状态,但只要我的wifi仍处于打开状态,即使关闭应用程序并清除RAM,我也仍然可以被发现。

问题

我的问题在于WifiP2pManager.PeerListListener中的WIFI_P2P_PEERS_CHANGED_ACTION一被触发就被触发。 我可以通过触发我的WiFiDirectBroadcastReceiver.class的回调函数检查附近是否有新的同龄人。

peerListListener本身中,peerListListener函数触发器将把所有新的对等项添加到我的onPeersAvailable中的ListView中,但不是这样。

有什么建议吗?

代码

清单

activity_main.xml

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="de.tu_chemnitz.dayliehelperprototype">

    <!-- Need to permission to restart JobServices after phone being shut down -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <!-- Permissions to use WIFI-Direct -->
    <uses-permission
        android:name="android.permission.ACCESS_WIFI_STATE"
        android:required="true" />
    <uses-permission
        android:name="android.permission.CHANGE_WIFI_STATE"
        android:required="true" />
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE"
        android:required="true" />
    <uses-permission
        android:name="android.permission.CHANGE_NETWORK_STATE"
        android:required="true" />
    <uses-permission
        android:name="android.permission.INTERNET"
        android:required="true" />

    <!-- Google Play filtering -->
    <uses-feature android:name="android.hardware.wifi.direct" android:required="true"/>

    <application
        android:allowBackup="true"
        android:fullBackupContent="true"
        android:icon="@mipmap/ic_app_icon"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_app_icon_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.VIEW"/>

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".JobSchedulerService"
            android:enabled="true"
            android:exported="true"
            android:permission="android.permission.BIND_JOB_SERVICE" />
    </application>
</manifest>

MainActivity.class

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:id="@+id/main_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        app:title="@string/app_name"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:fitsSystemWindows="true"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:paddingStart="16dp"
        android:paddingEnd="0dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.15">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center|start"
                android:text="@string/main_page_titel"
                android:textColor="@color/colorPrimaryDark"
                android:textSize="28sp"
                android:textStyle="bold" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.85"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="0.1"
                android:orientation="horizontal"
                android:baselineAligned="false">
                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="0.5">
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:text="@string/feature_option_1"
                        android:textSize="25sp"
                        android:textColor="@color/colorPrimary"
                        android:gravity="center|start"/>
                </LinearLayout>
                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="match_parent"
                    android:layout_weight="0.5"
                    android:gravity="center|end">
                    <Switch
                        android:id="@+id/notify_switch"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center"
                        android:textSize="18sp"
                        android:switchMinWidth="52dp"
                        android:theme="@style/mySwitchStyle"
                        android:layout_marginEnd="35dp"/>
                </LinearLayout>
            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="0.9"
                android:orientation="vertical"
                android:paddingEnd="30dp">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="0.15">
                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:text="Discovered Devices"
                        android:gravity="center|start"
                        android:textSize="28sp"
                        android:textStyle="bold"
                        android:textColor="@color/colorPrimaryDark"/>

                </LinearLayout>
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="0dp"
                    android:layout_weight="0.85">
                    <ListView
                        android:id="@+id/peerListView"
                        xmlns:android="http://schemas.android.com/apk/res/android"
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"/>
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>

WiFiDirectBroadcastReceiver.class

package de.tu_chemnitz.dayliehelperprototype;

import.*

import de.tu_chemnitz.dayliehelperprototype.utils.Utility;

public class MainActivity extends AppCompatActivity {

    private static final String NETWORK_STATE = "NETWORK_STATE";

    // UI elements
    Switch switchNotify;
    ListView listView;

    //Wifi Direct
    WifiP2pManager manager;
    WifiP2pManager.Channel channel;
    BroadcastReceiver receiver;
    IntentFilter intentFilter;
    List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
    String[] deviceNameArray;
    WifiP2pDevice[] deviceArray;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // define UI elements
        switchNotify =  findViewById(R.id.notify_switch);
        listView = findViewById(R.id.peerListView);

        initializeWifiDirect();

        // define toolbar
        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));

        //load default switch states [false], otherwise get it from sharedPreferences
        boolean state = Utility.getBool(this, "switch_states", "notify_switchkey");
        switchNotify.setChecked(state);

        switchNotify.setOnCheckedChangeListener(listener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(receiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(receiver);
    }

    WifiP2pManager.PeerListListener peerListListener = new WifiP2pManager.PeerListListener() {
        @Override
        public void onPeersAvailable(WifiP2pDeviceList peerList) {
            if(!peerList.getDeviceList().equals(peers)){
                peers.clear();
                peers.addAll(peerList.getDeviceList());

                deviceNameArray = new String[peerList.getDeviceList().size()];
                deviceArray = new WifiP2pDevice[peerList.getDeviceList().size()];
                int index = 0;
                // maybe we can get more information here
                for(WifiP2pDevice device : peerList.getDeviceList()){
                    deviceNameArray[index] = device.deviceName;
                    deviceArray[index] = device;
                    index++;
                }
                Log.d("this is my array", "arr: " + Arrays.toString(deviceNameArray));
                ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, deviceNameArray);
                listView.setAdapter(adapter);
            }

            if(peers.size() == 0){
                Log.d("WIFIDIRECT", "No devices found");
            }
        }
    };

    /**
     *   OnCheckedListeners for the switches
     */
    CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                if(Utility.isWiFiEnabled(MainActivity.this)){
                    Utility.customToastMsg(MainActivity.this,"Enabled", "#1abc9c");

                    startFindPeers();
                }
                else{
                    switchNotify.setChecked(false);
                    Utility.customToastMsg(MainActivity.this,"Wifi is disabled", "#FFB900");
                    isChecked = false;
                }

            } else {
                Utility.customToastMsg(MainActivity.this,"Disabled", "#ef5350");

                stopFindPeers();
            }
            // save current state [checked/unchecked]
            Utility.saveBool(MainActivity.this, "switch_states", "notify_switchkey", isChecked);
        }
    };


    public void startFindPeers(){
        if(manager != null){
            manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
                @Override
                public void onSuccess() {
                    Log.d(NETWORK_STATE, "Peer Discovery started");
                }

                @Override
                public void onFailure(int reason) {
                    Log.d(NETWORK_STATE, "Peer Discovery starting failed, failcode: " + reason);
                }
            });
        }
    }

    public void stopFindPeers(){
        if(manager != null){
            manager.stopPeerDiscovery(channel, new WifiP2pManager.ActionListener() {
                @Override
                public void onSuccess() {
                    Log.d(NETWORK_STATE, "Peer Discovery stopped");
                }

                @Override
                public void onFailure(int reason) {
                    Log.d(NETWORK_STATE, "Peer Discovery stopping failed, failcode: " + reason);
                }
            });
        }
    }

    public void initializeWifiDirect(){
        //Wifi Direct
        // This clall provides the API for managing Wifi peer-to-peer connectivity.
        manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
        // A channel that connects the application to the Wifi p2p framework.
        // Most p2p operations require a channel as an argument.
        if (manager != null) {
            channel = manager.initialize(this, getMainLooper(), null);
        }

        receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);

        intentFilter = new IntentFilter();

        intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
        intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);

    }
}

1 个答案:

答案 0 :(得分:0)

我发现了我的错误。

基本上我的代码是正确的,但是与Android版本有关。 我在Android Oreo(API 26)设备上执行了应用程序,但没有像我提到的那样工作。 peerList仍然为空。

今天,我在Android Nougat(API 24-25)设备上进行了尝试,并且成功了! peerList可以像往常一样将设备靠近附近。

最后,我将maxSDKVersion设置为25,现在可以在我的Android Oreo设备上使用了。

我不能真正说出为什么它的行为如此,但我认为与permissions有关。

编辑

没关系,我在这里发布的Android O +中遇到了这个问题 Peer discovery Issue with Oreo (Android 8+),解决方案是您需要获得SCAN_RESULTS_AVAILABLE_ACTION return empty list in Android 6.0此处提到的ACCESS_COARSE_LOCATION的许可。