简体   繁体   中英

bindService() reported errors with NullPointerException

I was trying to bind Service and Activity so that I can setup a service to get the time and present it on the activty. But the program reported errors as:

public void startTimeService(View v){
    startService(intent);
    Log.d(tag,"--startTimeService--");
      bindService(intent, con, Service.BIND_AUTO_CREATE);
        Log.d(tag,"post--startTimeService")**;
        tv.setText("current time is:/n"+mBinder.getService().getTime());

running the program can get the log as: --startTimeService-- and post--startTimeService,but report error still:

07-13 08:23:19.832: E/AndroidRuntime(3217): Caused by: java.lang. NullPointerException : Attempt to invoke virtual method 'com.himanmin.xu.servicedemo.TimeService com.himanmin.xu.servicedemo.TimeService$MyBinder.getService()' on a null object reference

the code TimeService.java is as following:

 public class TimeService extends Service {
    private final String tag = "TimeService";
    private int state;
    private int count;
    private boolean quit;

    public class MyBinder extends Binder{
        public TimeService getService(){
            Log.d(tag,"--getService()");
            return TimeService.this;
        }
    }

    private MyBinder mBinder = new MyBinder();

    public int getState(){
        //get the state of service
        Log.d(tag,"--getState()");
        return state;
    }

    public String getTime(){
        Log.d(tag,"--getTime()");
        SimpleDateFormat dateFormat24 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        //12 format 
        //SimpleDateFormat dateFormat12 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");  
        return dateFormat24.format(Calendar.getInstance().getTime());
    }

    public int getCount(){
        Log.d(tag,"--getCount()");
        return count;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(tag,"--onBind");
        System.out.println("Service is Binded");
        return mBinder;
    }

    @Override
    public void onCreate(){
        super.onCreate();
        Log.d(tag,"--onCreate");**
        System.out.println("Service for time is created");
        count = (int) System.currentTimeMillis();
    }
    @Override
    public boolean onUnbind(Intent intent){
        Log.d(tag,"--onUnbind");
        System.out.println("Serveice is unbinded");
        count = (int) (System.currentTimeMillis() - count);
        return true;
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        Log.d(tag,"--onDestroy");
        this.quit = true;
        System.out.println("Service for time is destoryed");
        count = (int) (System.currentTimeMillis() - count);
    }
}

After running bindService() ,method onCreate() of TimeService class will be invoked,it should be logcat --onCreate,but there is no such a log, taht means bindService(intent, con, Service.BIND_AUTO_CREATE) has not ran. I can not figure out the reason for that. intent and mainfest.xml is as follows:

private final String serviceAction = "com.himanmin.xu.servicedemo.TIME_SERVICE";

intent = new Intent();
intent.setAction(serviceAction);

<service android:name = "com.himanmin.xu.servicedemo.TimeService">
            <intent-filter>
                <action android:name="com.himanmin.xu.servicedemo.TIME_SERVICE"/>
            </intent-filter>
        </service>

Can you guys help me to figure the problem out?

The problem seems to be that the service takes time to start. When you call:

bindService(intent, con, Service.BIND_AUTO_CREATE);

The method will fire an intent and return immediately. Then Android system will start your service at the soonest available time. Therefore when you call:

tv.setText("current time is:/n"+mBinder.getService().getTime());

your service hasn't started yet, which is why you get a null pointer exception.

To solve this, you must implement a service connection as described in Android Bound Services doc page (modified slightly to fit your case):

/** 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
        mBinder = (MyBinder) service;
        tv.setText("current time is:/n"+mBinder.getService().getTime());
        mBound = true;
    }

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

Only after your onServiceConnected method is called and mBound is set to true can you use the mBinder object.

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