1

I keep getting the same error, Unable to start activity ... java.lang.NullPointerException: Attempt to invoke virtual method ... on a null object reference, every time I try to invoke a function in a service from an activity.

The error is below.

10-18 22:30:46.371 1773-1773/com.example.test I/art: Not late-enabling -Xcheck:jni (already on)
10-18 22:30:47.054 1773-1785/com.example.test I/art: Background sticky concurrent mark sweep GC freed 2727(238KB) AllocSpace objects, 0(0B) LOS objects, 17% free, 939KB/1135KB, paused 19.920ms total 60.374ms
10-18 22:30:47.070 1773-1773/com.example.test D/AndroidRuntime: Shutting down VM
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: FATAL EXCEPTION: main
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: Process: com.example.test, PID: 1773
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.test.MyService.getRandomNumber()' on a null object reference
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.access$800(ActivityThread.java:144)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:135)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5221)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.test.MyService.getRandomNumber()' on a null object reference
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at com.example.test.MainActivity.onCreate(MainActivity.java:27)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.Activity.performCreate(Activity.java:5937)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.access$800(ActivityThread.java:144) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.os.Handler.dispatchMessage(Handler.java:102) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.os.Looper.loop(Looper.java:135) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at android.app.ActivityThread.main(ActivityThread.java:5221) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Native Method) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at java.lang.reflect.Method.invoke(Method.java:372) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
10-18 22:30:58.000 1773-1780/com.example.test W/art: Suspending all threads took: 12.169ms
10-18 22:31:27.545 1773-1780/com.example.test W/art: Suspending all threads took: 17.580ms
10-18 22:31:31.555 1773-1780/com.example.test W/art: Suspending all threads took: 18.440ms
10-18 22:31:39.070 1773-1780/com.example.test W/art: Suspending all threads took: 11.531ms
10-18 22:31:51.100 1773-1780/com.example.test W/art: Suspending all threads took: 5.540ms

The MainActivity is below.

package com.example.test;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    MyService mService;
    boolean mBound = false;

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

        // Bind this and the service together
        Intent noiseIntent = new Intent(this, MyService.class);
        bindService(noiseIntent, mConnection, Context.BIND_AUTO_CREATE);
        startService(noiseIntent);

        int num = mService.getRandomNumber();
        Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
    }

    /** Defines callbacks for service binding, passed to bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            MyService.ServiceBinder binder = (MyService.ServiceBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

And the MyService is below.

package com.example.test;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

import java.util.Random;

public class MyService extends Service {
    // Binder given to clients
    private final IBinder mBinder = new ServiceBinder();
    // Random number generator
    private final Random mGenerator = new Random();

    /**
     * Class used for the client Binder.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with IPC.
     */
    public class ServiceBinder extends Binder {
        MyService getService() {
            // Return this instance of LocalService so clients can call public methods
            return MyService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * method for clients
     */
    public int getRandomNumber() {
        return mGenerator.nextInt(100);
    }
}

I've been stuck on this for a couple of hours and I couldn't find any solutions. Any help would be appreciated. :D

1 Answers1

6

Both bindService() and startService() are asynchronous. Your mService object will be null until onServiceConnected() is called, so you cannot use it until that point.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • So by what you've said, I thought of reordering the `ServiceConnection` to be before `onCreate` and it gave me the same error. But I've noticed if I change the `public int getRandomNumber() { return mGenerator.nextInt(100); }` to `public static int getRandomNumber() { return 10; }`, then it works flawlessly. But I don't want it to be a static. Any suggestions? – FantasiesAndFailures Oct 18 '15 at 22:48
  • 1
    @user5460708: In the Java programming language, the order in which things appear in the source file has nothing to do with the execution order. Move your `mService.getRandomNumber()` call *into* `onServiceConnected()`, after you have assigned `mService` a value. – CommonsWare Oct 18 '15 at 22:51
  • I've moved the `getRandomNumber()` and ` Toast.makeText` into `onServiceConnected()` and it worked perfectly without it being static. But why must I move it into there when I've assigned `mService` in the class and updated it in the `onServiceConnected()`, shouldn't it just work everywhere else? And what if I need to use a function from outside the service else where, for example a button listener (when the function from the service be invoked from outside of `onServiceConnected`)? – FantasiesAndFailures Oct 18 '15 at 23:04
  • @user5460708: "shouldn't it just work everywhere else?" -- only *after `onServiceConnected()` has been called*, as it is only then that you have a value for `mService`. The issue is not one of where lines reside in the file, but one of time. – CommonsWare Oct 18 '15 at 23:09
  • @CommonsWare Except in the cases of static initializer blocks, non-static initializer blocks, declarations with initializers, ... – user207421 Oct 19 '15 at 09:44