android - 接收广播时出错 Intent act=android.net.wifi.p2p.THIS_DEVICE_CHANGED

标签 android android-intent

我正在尝试整合 this我的应用程序中的 wifi p2p 示例。但是调用 Activity 时出现此错误:

Process: com.github.hiteshsondhi88.sampleffmpeg, PID: 8157
java.lang.RuntimeException: Error receiving broadcast Intent { act=android.net.wifi.p2p.THIS_DEVICE_CHANGED flg=0x4000010 (has extras) } in it.linup.maint.activity.WiFiDirectBroadcastReceiver@7aa8d91
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:979)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void it.linup.maint.activity.DeviceListFragment.updateThisDevice(android.net.wifi.p2p.WifiP2pDevice)' on a null object reference
at it.linup.maint.activity.WiFiDirectBroadcastReceiver.onReceive(WiFiDirectBroadcastReceiver.java:91)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:969)
at android.os.Handler.handleCallback(Handler.java:743) 
at android.os.Handler.dispatchMessage(Handler.java:95) 
at android.os.Looper.loop(Looper.java:150) 
at android.app.ActivityThread.main(ActivityThread.java:5665) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712) 

这是wifi direct的 Activity

package it.linup.maint.activity;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.provider.*;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.*;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

import com.github.hiteshsondhi88.sampleffmpeg.R;

import static android.os.Looper.getMainLooper;

public class P2P  extends Activity implements WifiP2pManager.ChannelListener, DeviceListFragment.DeviceActionListener {

public static final String TAG = "wifidirectdemo";
private WifiP2pManager manager;
private boolean isWifiP2pEnabled = false;
private boolean retryChannel = false;

private final IntentFilter intentFilter = new IntentFilter();
private WifiP2pManager.Channel channel;
private BroadcastReceiver receiver = null;

/**
 * @param isWifiP2pEnabled the isWifiP2pEnabled to set
 */
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
    this.isWifiP2pEnabled = isWifiP2pEnabled;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // add necessary intent values to be matched.

    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);

    manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
    channel = manager.initialize(this, getMainLooper(), null);

}

/** register the BroadcastReceiver with the intent values to be matched */
@Override
public void onResume() {
    super.onResume();
    receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
    registerReceiver(receiver, intentFilter);
}

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

/**
 * Remove all peers and clear all fields. This is called on
 * BroadcastReceiver receiving a state change event.
 */
public void resetData() {
    DeviceListFragment fragmentList = (DeviceListFragment) getFragmentManager()
            .findFragmentById(R.id.frag_list);
    DeviceDetailFragment fragmentDetails = (DeviceDetailFragment) getFragmentManager()
            .findFragmentById(R.id.frag_detail);
    if (fragmentList != null) {
        fragmentList.clearPeers();
    }
    if (fragmentDetails != null) {
        fragmentDetails.resetViews();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.action_items, menu);
    return true;
}

/*
 * (non-Javadoc)
 * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
 */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.atn_direct_enable:
            if (manager != null && channel != null) {

                // Since this is the system wireless settings activity, it's
                // not going to send us a result. We will be notified by
                // WiFiDeviceBroadcastReceiver instead.

                startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
            } else {
                android.util.Log.e(TAG, "channel or manager is null");
            }
            return true;

        case R.id.atn_direct_discover:
            if (!isWifiP2pEnabled) {
                Toast.makeText(P2P.this, R.string.p2p_off_warning,
                        Toast.LENGTH_SHORT).show();
                return true;
            }
            final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
                    .findFragmentById(R.id.frag_list);
            fragment.onInitiateDiscovery();
            manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {

                @Override
                public void onSuccess() {
                    Toast.makeText(P2P.this, "Discovery Initiated",
                            Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(int reasonCode) {
                    Toast.makeText(P2P.this, "Discovery Failed : " + reasonCode,
                            Toast.LENGTH_SHORT).show();
                }
            });
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

@Override
public void showDetails(WifiP2pDevice device) {
    DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
            .findFragmentById(R.id.frag_detail);
    fragment.showDetails(device);

}

@Override
public void connect(WifiP2pConfig config) {
    manager.connect(channel, config, new WifiP2pManager.ActionListener() {

        @Override
        public void onSuccess() {
            // WiFiDirectBroadcastReceiver will notify us. Ignore for now.
        }

        @Override
        public void onFailure(int reason) {
            Toast.makeText(P2P.this, "Connect failed. Retry.",
                    Toast.LENGTH_SHORT).show();
        }
    });
}

@Override
public void disconnect() {
    final DeviceDetailFragment fragment = (DeviceDetailFragment) getFragmentManager()
            .findFragmentById(R.id.frag_detail);
    fragment.resetViews();
    manager.removeGroup(channel, new WifiP2pManager.ActionListener() {

        @Override
        public void onFailure(int reasonCode) {
            android.util.Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);

        }

        @Override
        public void onSuccess() {
            fragment.getView().setVisibility(View.GONE);
        }

    });
}

@Override
public void onChannelDisconnected() {
    // we will try once more
    if (manager != null && !retryChannel) {
        Toast.makeText(this, "Channel lost. Trying again", Toast.LENGTH_LONG).show();
        resetData();
        retryChannel = true;
        manager.initialize(this, getMainLooper(), this);
    } else {
        Toast.makeText(this,
                "Severe! Channel is probably lost premanently. Try Disable/Re-Enable P2P.",
                Toast.LENGTH_LONG).show();
    }
}

@Override
public void cancelDisconnect() {

    /*
     * A cancel abort request by user. Disconnect i.e. removeGroup if
     * already connected. Else, request WifiP2pManager to abort the ongoing
     * request
     */
    if (manager != null) {
        final DeviceListFragment fragment = (DeviceListFragment) getFragmentManager()
                .findFragmentById(R.id.frag_list);
        if (fragment.getDevice() == null
                || fragment.getDevice().status == WifiP2pDevice.CONNECTED) {
            disconnect();
        } else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE
                || fragment.getDevice().status == WifiP2pDevice.INVITED) {

            manager.cancelConnect(channel, new WifiP2pManager.ActionListener() {

                @Override
                public void onSuccess() {
                    Toast.makeText(P2P.this, "Aborting connection",
                            Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onFailure(int reasonCode) {
                    Toast.makeText(P2P.this,
                            "Connect abort request failed. Reason Code: " + reasonCode,
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
    }

  }
}

这与示例基本相同。

这是广播接收器类

package it.linup.maint.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pManager;
import android.util.*;

import com.github.hiteshsondhi88.sampleffmpeg.R;

/**
* Created by utente on 10/04/2017.
*/

public class WiFiDirectBroadcastReceiver extends BroadcastReceiver {

private WifiP2pManager manager;
private WifiP2pManager.Channel channel;
private P2P activity;

/**
 * @param manager WifiP2pManager system service
 * @param channel Wifi p2p channel
 * @param activity activity associated with the receiver
 */
public WiFiDirectBroadcastReceiver(WifiP2pManager manager, WifiP2pManager.Channel channel,
                                   P2P activity) {
    super();
    this.manager = manager;
    this.channel = channel;
    this.activity = activity;
}

/*
 * (non-Javadoc)
 * @see android.content.BroadcastReceiver#onReceive(android.content.Context,
 * android.content.Intent)
 */
@Override
public void onReceive(Context context, Intent intent) {
    String action = intent.getAction();
    if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {

        // UI update to indicate wifi p2p status.
        int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);
        if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
            // Wifi Direct mode is enabled
            activity.setIsWifiP2pEnabled(true);
        } else {
            activity.setIsWifiP2pEnabled(false);
            activity.resetData();

        }
        android.util.Log.d(P2P.TAG, "P2P state changed - " + state);
    } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {

        // request available peers from the wifi p2p manager. This is an
        // asynchronous call and the calling activity is notified with a
        // callback on PeerListListener.onPeersAvailable()
        if (manager != null) {
            manager.requestPeers(channel, (WifiP2pManager.PeerListListener) activity.getFragmentManager()
                    .findFragmentById(R.id.frag_list));
        }
        android.util.Log.d(P2P.TAG, "P2P peers changed");
    } else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {

        if (manager == null) {
            return;
        }

        NetworkInfo networkInfo = (NetworkInfo) intent
                .getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);

        if (networkInfo.isConnected()) {

            // we are connected with the other device, request connection
            // info to find group owner IP

            DeviceDetailFragment fragment = (DeviceDetailFragment) activity
                    .getFragmentManager().findFragmentById(R.id.frag_detail);
            manager.requestConnectionInfo(channel, fragment);
        } else {
            // It's a disconnect
            activity.resetData();
        }
    } else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {
        DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
                .findFragmentById(R.id.frag_list);
        fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
                WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));

    }
 }
}

我已经在 list 中添加了所有必需的权限

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

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />


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

<application
    android:allowBackup="true"
    android:icon="@drawable/launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    <activity
        android:name="it.linup.maint.activity.Main"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustPan" android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

    </activity>
    <activity
        android:name="it.linup.maint.activity.Home"
        android:label="Home"
        android:screenOrientation="portrait"></activity>
    <activity
        android:name="it.linup.maint.activity.Log"
        android:label="Log"
        android:screenOrientation="portrait"></activity>
    <activity
        android:name="it.linup.maint.activity.Settings"
        android:label="Settings"
        android:screenOrientation="portrait"></activity>
    <activity
        android:name="it.linup.maint.activity.DebugActivity"
        android:screenOrientation="portrait"></activity>
    <activity
        android:name="it.linup.maint.activity.Help"
        android:screenOrientation="portrait"></activity>
    <activity android:name="it.linup.maint.activity.P2P" >

    </activity>
</application>

该应用程序由一个 tabhost 组成,其中包含链接到三个 Activity 的三个选项卡。当我单击 P2P Activity 上的选项卡时,应用程序出现错误,显示上面发布的错误。奇怪的是,如果我从头开始创建一个项目,只包含与 wifi direct 相关的类,那么一切正常。

感谢帮助

最佳答案

你得到一个NullPointerException:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void
it.linup.maint.activity.DeviceListFragment.updateThisDevice(android.net.wifi.p2p.WifiP2pDevice)'
on a null object reference
at it.linup.maint.activity.WiFiDirectBroadcastReceiver.onReceive(WiFiDirectBroadcastReceiver.java:91)

这意味着在这段代码中:

    DeviceListFragment fragment = (DeviceListFragment) activity.getFragmentManager()
            .findFragmentById(R.id.frag_list);
    fragment.updateThisDevice((WifiP2pDevice) intent.getParcelableExtra(
            WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));

变量 fragmentnull(暗示调用 findFragmentById() 返回 null

关于android - 接收广播时出错 Intent act=android.net.wifi.p2p.THIS_DEVICE_CHANGED,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43339940/

相关文章:

java - 解析删除对象

java - 从 Android 应用程序在 openfire 上创建一个组

Android - MEDIA ERROR UNKNOWN -1 通常意味着什么

Android,广播可打包数据

java - onActivityResult 在 API 级别 17 下未调用

android - 使用主页按钮退出时如何恢复操作?

java - 将 MySQL 日期转换为 Java 日期 : Android

android - 无法构建发布应用程序,gradle 说找不到封闭方法 'boolean onCreateOptionsMenu(android.view.Menu)

android - Android 中的底部共享表

android - 如何将操作栏中搜索中输入的文本转换为字符串?