简体   繁体   中英

Android Broadcastreceiver crashes when my onlinestate changes

I have extended a Broadcastreceiver so that my app knows whenever the online state has been changed. The thing is: whenever the online state changes, my broadcastreceiver seems to get reconstructed. Because I add a listener on a later moment than the constructor, my listener is empty and I get a NullPointerException:

02-07 11:11:45.804: E/AndroidRuntime(21416): FATAL EXCEPTION: main
02-07 11:11:45.804: E/AndroidRuntime(21416): java.lang.RuntimeException: Unable to start receiver nl.raakict.android.dnd.util.NetworkStateReceiver: java.lang.NullPointerException
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.app.ActivityThread.handleReceiver(ActivityThread.java:2699)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.app.ActivityThread.access$1500(ActivityThread.java:162)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1453)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.os.Looper.loop(Looper.java:158)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.app.ActivityThread.main(ActivityThread.java:5751)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at java.lang.reflect.Method.invokeNative(Native Method)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at java.lang.reflect.Method.invoke(Method.java:511)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1083)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:850)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at dalvik.system.NativeStart.main(Native Method)
02-07 11:11:45.804: E/AndroidRuntime(21416): Caused by: java.lang.NullPointerException
02-07 11:11:45.804: E/AndroidRuntime(21416):    at nl.raakict.android.dnd.util.NetworkStateReceiver.onReceive(NetworkStateReceiver.java:38)
02-07 11:11:45.804: E/AndroidRuntime(21416):    at android.app.ActivityThread.handleReceiver(ActivityThread.java:2687)
02-07 11:11:45.804: E/AndroidRuntime(21416):    ... 10 more

My custom broadcastreceiver looks like this:

package nl.raakict.android.dnd.util;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

public class NetworkStateReceiver extends BroadcastReceiver{ 
    private Listener mListener = null;
    private static NetworkStateReceiver _instance;

    public static NetworkStateReceiver getInstance()
    {
        if (_instance == null)
        {
            _instance = new NetworkStateReceiver();
        }
        return _instance;
    }

    public NetworkStateReceiver(){
    }

    @Override
    public void onReceive(Context context, Intent intent) {
     Log.d("app","Network connectivity change");
     if(intent.getExtras()!=null) {
        NetworkInfo ni=(NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
        if(ni!=null && ni.getState()==NetworkInfo.State.CONNECTED) {
            Log.i("app","Network "+ni.getTypeName()+" connected");
            mListener.onStateChange(true);
        }
     }
     if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
            Log.d("app","There's no network connectivity");
            mListener.onStateChange(false);
     }
   }

    public interface Listener {
        public void onStateChange(boolean state);
    }

    public void registerListener (Listener listener) {
        mListener = listener;
    }

    public boolean isOnline(Context context) {
        ConnectivityManager cm =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnectedOrConnecting()) {
            return true;
        }
        return false;
    }

}

and my manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="nl.raakict.android.dnd"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="nl.raakict.android.dnd.HomeActivity"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:label="@string/app_name"
            android:theme="@style/FullscreenTheme" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
            <receiver android:name="nl.raakict.android.dnd.util.NetworkStateReceiver">
           <intent-filter>
              <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
           </intent-filter>
        </receiver>
    </application>
</manifest>

And this is my listener class:

public class RequestHandler implements NetworkStateReceiver.Listener {

    private static RequestHandler _instance;
    private NetworkStateReceiver networkStateReveiver;
    private ArrayList<CustomJsonRequest> delayedRequestQueue;
    private boolean currentlyOnline;
    private Context applicationContext;


    public static RequestHandler getInstance(Context applicationContext)
    {
        if (_instance == null)
        {
            _instance = new RequestHandler(applicationContext);
        }
        return _instance;
    }

    private RequestHandler(Context applicationContext){
        delayedRequestQueue= new ArrayList<CustomJsonRequest>();
        this.applicationContext = applicationContext;
        networkStateReveiver = NetworkStateReceiver.getInstance();
        networkStateReveiver.registerListener(this);
        currentlyOnline = networkStateReveiver.isOnline(applicationContext);
    }

    @Override
    public void onStateChange(boolean online) {
        // TODO Auto-generated method stub
        currentlyOnline = online;
        if(online){
            sendRequestQueue();
        }
    }

    public void newPostRequest(CustomJsonRequest request) {
        delayedRequestQueue.add(request);
        if(currentlyOnline) 
            sendRequestQueue();
    }

    public void sendRequestQueue(){
        //code logic here
    }
}

What did I do wrong?

The problem is that when Network State is being done, Android will create your NetworkStateReceiver class instance, call its onReceive and then destroy your receiver instance. So that is why your listener is always null, if you want to inform some other components of network change then you should for example send local broadcast in your application.

You might alswo register local BroadcastReceiver:

"Register your BroadcastReceiver programmatically": http://www.grokkingandroid.com/android-tutorial-broadcastreceiver/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM