SharedPrefencesChangeListener is not working in this code. Please point out if anything is missed.
I am wondering if it is happening because I have declared it in a service.
Code to change the SharedPreferences from another activity:
getSharedPreferences("TRACKER", Context.MODE_PRIVATE).edit().putString("TRIP_LIST", String.valueOf(trip_list)).apply();
///
package com.tracker;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import org.json.JSONException;
import org.json.JSONObject;
public class SharedPrefMonService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener {
LocalBroadcastManager broadcaster = LocalBroadcastManager.getInstance(this);
public SharedPrefMonService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.unregisterOnSharedPreferenceChangeListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
prefs.registerOnSharedPreferenceChangeListener(this);
return Service.START_STICKY;
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals("TRIP_LIST")){
try {
JSONObject trip_list = new JSONObject(sharedPreferences.getString("TRIP_LIST", "{}"));
if(trip_list.keys().hasNext()){
//start location service
}else{
//stop location service
}
//update trip list view here
Intent intent = new Intent("SharedPrefMonService");
intent.putExtra("updated_trip_list", trip_list.toString());
broadcaster.sendBroadcast(intent);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
It's not that you have the listener in a Service, necessarily. You're not setting the listener on the same SharedPreferences that you're modifying.
Context#getSharedPreferences() creates a SharedPreferences with the name you give it. PreferenceManager.getDefaultSharedPreferences() creates a SharedPreferences from your package name with _preferences appended. They're both ultimately XML files, but a listener on one won't be notified of changes on another.
Either change the SharedPreferences you're modifying to use the default - PreferenceManager.getDefaultSharedPreferences() - or set your listener on the one you're currently saving to - getSharedPreferences("TRACKER", Context.MODE_PRIVATE).
I would also mention that an OnSharedPreferenceChangeListener will only fire when a particular key's value changes. If you save a key with the same value it already had, onSharedPreferenceChanged() won't run.
Related
Long story short, I have a class that handles my app shared preferences.
I call it from various other classes without issues, but when I try to call it from my service (from the same APK) I get a null exception. I am guessing that it's getting called from the wrong context or something like that. Here is the relevant code.
MainActivity.java
package com.deskwizard.audiomanager;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.deskwizard.audiomanager.DataSaveRestore;
public class MainActivity extends FragmentActivity {
public static Context contextOfApplication;
final FragmentManager fm = getFragmentManager();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contextOfApplication = getApplicationContext();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_settings, new FadeBalanceFragment());
ft.commit();
// TODO: Load previously saved settings for all values
DataSaveRestore.restore_all();
// TODO: init I2C
}
public static Context getContextOfApplication() {
return contextOfApplication;
}
}
DataSaveRestore.java (defaultpreferences class)
package com.deskwizard.audiomanager;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
public class DataSaveRestore extends Application {
// Data variables
public static int Bass_level, Bass_CFreq, Bass_Qfact, Sub_level,
Sub_Lowpass, Treble_level, Treble_CFreq, Mid_level, Mid_CFreq,
Mid_Qfact, Fade, Balance, Loudness_level, Loudness_freq,
Loudness_boost;
static boolean Bass_DCMode, Loudness_state;
static Context applicationContext = MainActivity.getContextOfApplication();
public static void restore_all() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(applicationContext);
if (prefs.getInt("data_saved", 0) == 0) {
set_defaults();
load_defaults();
} else {
load_defaults();
}
//TODO: send settings to TDA7418
DS3903.set_lowpass(DataSaveRestore.Sub_Lowpass);
};
Service code snippet:
public class AudioManagerService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO do something useful
Log.d("com.deskwizard.audiomanager", "starting service...");
DataSaveRestore.restore_all(); // restore settings to TDA7418/DS3903
start();
return Service.START_STICKY;
}
The Null Exception error refers to this line, only when called from the service, it works properly from the main application and other classes:
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(applicationContext);
Let me know if any further code can help narrow it down.
Thanks,
DW
Because, In your service when you call, DataSaveRestore.restore_all(); It make reference on, (As there is no MainActivity context available from Servce)
static Context applicationContext = MainActivity.getContextOfApplication();
on this line, applicationContext will be null as it can't find MainActivity initialization
Simply, Just change your restore_all() method from Application class.
First remove static and and use getApplicationContext() of Android application class method to get application context as in Service,
public void restore_all() {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
if (prefs.getInt("data_saved", 0) == 0) {
set_defaults();
load_defaults();
} else {
load_defaults();
}
//TODO: send settings to TDA7418
DS3903.set_lowpass(DataSaveRestore.Sub_Lowpass);
};
Now call, restore_all(); by initializing object of Application class not a static way.
Like,
DataSaveRestore dataSaveRestore = (DataSaveRestore) getApplicationContext();
dataSaveRestore.restore_all();
I'm trying to use a Content Observer to update a Service when any changes happen to the sqlite database in my app.
I'm confused as to what to do, so I put together some code below. Usually, Content Observers are used with contacts or mediaplayer with a background service. In my research I read that it can be used with the sqlite database on the phone.
Questions:
1. Since Sqlite database does not have a uri, what info do I replace People.CONTENT_URI in
this.getContentResolver().registerContentObserver (People.CONTENT_URI, true, contentObserver);
2. In my research I didn't find any code that would go into the database class that would alert the ContentObserver. Does all the code for the Content Observer work within the service class?
Note that this question is similar to Android SQLite DB notifications and
how to listen for changes in Contact Database
Both questions do not explicitly answer my question. If you have code that explains this, that would be very helpful.
Here is my semi-pusedo code below. It does not work. I'm using it to learn about how to update a service when the database info changes.
package com.example.com.test.content.observer;
import java.sql.Date;
import java.util.Calendar;
import java.util.List;
import com.google.android.gcm.demo.app.Alerts.AlarmsService;
import com.google.android.gcm.demo.app.Alerts.Alerts;
import com.google.android.gcm.demo.app.sqllite.DatabaseSqlite;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.provider.Contacts.People;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.database.ContentObserver;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import android.support.v4.app.NavUtils;
public class AlarmService extends Service
{
Handler mHandler = new Handler();
DatabaseSqlite db = new DatabaseSqlite(this);
List<Alerts> listAlerts;
PendingIntent pendingIntent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.getApplicationContext()
.getContentResolver()
.registerContentObserver(?????, true,
contentObserver);
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("TAG", "started onstart command Created from Alerts service .");
return super.onStartCommand(intent, flags, startId);// START_STICKY;
}
#Override
public void onStart(final Intent intent, int startId) {
super.onStart(intent, startId);
runThread();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed...", Toast.LENGTH_LONG).show();
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private class MyContentObserver extends ContentObserver {
#SuppressLint("ParserError")
public MyContentObserver(Handler mHandler) {
super(mHandler);
}
#Override
public void onChange(boolean selfChange) {
runThread();
super.onChange(selfChange);
}
public void runThread(){
Thread thread = new Thread() {
#Override
public void run() {
Boolean x = true;
while (x) {
db.open();
listAlerts = db.getAlarmsForService();
db.close();
int alerts=listAlerts.size();
for (int i = 0; i < alerts; i++) {
Alerts item = listAlerts.get(i);
item.getRowId();
item.getRemoteServerId();
String alertInMills = item.getAlertDateInMills();
String alertDuration = item.getAlertDurationInMinutes();
String eventName = item.getEventName();
long longAlertInMills = Long.parseLong(alertInMills);
pendingIntent = PendingIntent.getService(AlarmsService.this, 0,intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
// go to data base for time in mills
calendar.setTimeInMillis(longAlertInMills);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
//
System.out.println(calendar.toString());
}
//
System.out.println("thread");
x = false;
}
}
};
thread.start();
}
}
MyContentObserver contentObserver = new MyContentObserver(mHandler);
this.getContentResolver().registerContentObserver (People.CONTENT_URI, true, contentObserver);
}
In general, there are two parts to handling this: you have the ContentObserver which needs to register to receive changes, as you've pointed out, and the SQLiteDatabase which has to notify the registered observers of any changes. If this is a database you own, you can create the URI that you can use to listen for.
(1) First define your URI, typically in your Database definition file.
public static final Uri CONTENT_URI = Uri.parse("mycontent://packagename/something");
(2) for your database Content Provider:
Each db function (insert, update, delete) should call through to notifyChange() after completing the operation in order to inform the observers that changes have happened.
rowId = db.insert(tableName, null, cv);
...
getContext().getContentResolver().notifyChange(newUri, null);
(3) Create and register your ContentObserver in the Service, as described in the same link you provided above (remember to override the deliverSelfNotifications() to return true)
public class MyService extends Service {
private MyContentObserver mObserver;
#Override
public void onStartCommand(Intent intent, int flags, int startId) {
...
mObserver = new MyContentObserver();
getContentResolver().registerContentObserver(Dbfile.CONTENT_URI, null, mObserver);
}
#Override
public void onDestroy() {
...
if (mObserver != null) {
getContentResolver().unregisterContentObserver(mObserver);
mObserver = null;
}
}
// define MyContentObserver here
}
(4) In your ContentObserver.onChange(), you can post something to the Service or handle the change right there if possible.
Also, if it helps your cause, you can customize the URI definition to handle different types of data that you are observing, register your observer for each URI, and then override ContentObserver.onChange(boolean, Uri) instead.
Hope this helps!
I've really tried to get through the intent.putExtra() and getIntent().getExtras() and apply them to one of the SimpleService tutorials. I know a lot of people have already asked "why is bundle extras always null?" I promise I tried to hack through the answers I found here for several hours before I considered posting but I don't think I'm advanced enough to really understand what it is I must be doing wrong with the minor snippets people are posting. As such I put in the full code of my activity and my service.
I think my issue is the that my starting intent (the one I create in my activity) doesn't exist in the context of my service. I wonder if maybe I'm using Intents in the wrong direction/purpose entirely? I did try an intent.putExtra in my service, to try to send a string the other direction, but those extras are always null, too. So at the risk of repetition, why is bundle extras always null? How do I make a single intent that exists both in the context of my activity and my service?
I should note that the code as displayed below obviously will have a null extras because I've commented out a few of my attempts to .getExtras() that have failed. I deleted the rest for the sake of cleanliness.
EDIT: The answer thanks to the replies, in code for the sake of those who have also been Googling for hours. Put this in your service (please note that the return START_REDELIVER_INTENT may be wrong):
#Override
public int onStartCommand( Intent intent , int flags , int startId )
{
super.onStartCommand(intent, flags , startId);
extras = intent.getExtras();
//just checking
if( extras != null )
Toast.makeText(this,extras.getString("extratoservice"), Toast.LENGTH_SHORT).show();
return START_REDELIVER_INTENT;
}
My activity (based on Sai Geetha's blog):
package com.example.BroadcastIntent;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class BroadcastIntentActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button start = (Button)findViewById(R.id.buttonStart);
start.setOnClickListener(startListener);
Button stop = (Button)findViewById(R.id.buttonStop);
stop.setOnClickListener(stopListener);
//the intent I'm using to start and stop the service -- the extras don't go anywhere....
intent = new Intent(BroadcastIntentActivity.this,BroadcastService.class);
intent.putExtra("extratoservice", "if you can read this, it made it to the service" );
}
Boolean serviceRunning;
Intent intent;
//Clicks from Geetha's Blog
private OnClickListener startListener = new OnClickListener() {
public void onClick(View v){
startService(intent);
serviceRunning = true;
}
};
private OnClickListener stopListener = new OnClickListener() {
public void onClick(View v){
try
{
stopService(intent);
serviceRunning = false;
}
catch( Exception e)
{
Toast.makeText(getApplicationContext(), "Service was not running...",Toast.LENGTH_SHORT).show();
}
}
};
}
And this is my service:
package com.example.BroadcastIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.widget.Toast;
public class BroadcastService extends Service{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
//extras = arg0.getExtras(); <-- this has null extras, too...
return null;
}
Bundle extras;
#Override
public void onCreate() {
super.onCreate();
// extras = getIntent().getExtras(); <-- this is undefined?
if( extras == null )
Toast.makeText(this,"Service created... extras still null", Toast.LENGTH_SHORT).show();
else
Toast.makeText(this,extras.getString("extratoservice"), Toast.LENGTH_SHORT).show();
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service destroyed ...", Toast.LENGTH_SHORT).show();
}
}
you need to look at the onStartCommand() function (I'm not at a desktop so I can't conveniently link to the javadoc). This will receive the intent you passed and your extras should be available there.
I think you need to do this in your service..
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
to get the intent you're passing in... but I'm not 100% on this, so double check
http://developer.android.com/reference/android/app/Service.html
I'm trying to create a service which will start by the user request in the application.
After the user will choose an update interval, the service will run in the operation system background, and will send a non-relevant message.
I've tried to write the service according to the example for Service class API.
For some reason, I figured in debug (when running doBindService() method) that mUpdateBoundService is getting null.
My second question is whether I can use "Toast" inform message outside an application ? (As kind of a desktop notification).
Can anyone help ? Here is my short code:
UpdateService.java
package android.update;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class UpdateService extends Service {
private NotificationManager mNM;
private final IBinder mBinder = new UpdateBinder();
private int updateInterval;
public class UpdateBinder extends Binder {
UpdateService getService() {
return UpdateService.this;
}
}
public void onCreate() {
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
Timer timer = new Timer();
timer.schedule(new UpdateTimeTask(), 100, updateInterval);
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
class UpdateTimeTask extends TimerTask {
public void run() {
showNotification();
}
}
public void showNotification() {
Toast.makeText(this, "Hi", 10);
}
#Override
public IBinder onBind(Intent intent) {
updateInterval = intent.getExtras().getInt(getString(R.string.keyUpdateInterval));
return mBinder;
}
}
UpdateActivity.java
package android.update;
import android.app.Activity;
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.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class UpdateActivity extends Activity {
private UpdateService mUpdateBoundService;
private boolean mIsBound = false;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onClickStartUpdateService(View view) {
switch (view.getId()) {
case R.id.btnStartUpdateService:
doBindService();
//Toast.makeText(this,"Service Started",Toast.LENGTH_LONG).show();
mUpdateBoundService.showNotification();
break;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mUpdateBoundService = ((UpdateService.UpdateBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mUpdateBoundService = null;
}
};
private void doBindService() {
Intent updateActivityIntent = new Intent(UpdateActivity.this,
UpdateService.class);
EditText txtUpdateInterval = (EditText) findViewById(R.id.txtUpdateInterval);
int interval = Integer.parseInt(txtUpdateInterval.getText().toString());
updateActivityIntent.putExtra(getString(R.string.keyUpdateInterval), interval);
bindService(updateActivityIntent, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
}
Your toast is not showing because you are not telling it to. Try:
public void showNotification() {
Toast.makeText(this, "Hi", 10).show();
}
For your service issue, I think that you do not properly understand how services & activities work together. A service can run independently of a service, or you can have a service whose lifecycle matches that of a given activity. From your code, it is not clear which of these models you are following. Your implementation will cause the service to wake periodically, but only while your activity is running. If the user switches to another activity, your service will no longer be woken.
If you want a service to wake periodically independently of the activity, then you need to run your timer event in the service itself. Better still use an Alarm to wake your service: Register an Alarm with AlarmManager which will fire an Intent at a future point (or regular intervals, if you prefer), and extend your service from IntentService, override onHandleIntent() and add the necessary Intent Filter to your Service entry in the manifest.
I was writing a simple AIDL based android remote service & a client to access the API exposed by the remote service. I checked on the internet, in every posts people have called the remote service API inside button's onClickListener() method of client code. However when i tried to call the API exposed by remote service outside the onClickListener() method it throws me NullPointerException, indicating that my service object has not been initialized (Please check the comments inside the onCreate method of client code). I have attached my code with this question. If anyone can explain me why is the behavior so then that would be really great.
Here is client code :
package com.myapp.myclient;
import android.app.Activity;
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.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.myapp.myservice.RemoteServiceInterface;
public class MyClient extends Activity {
RemoteServiceInterface remoteInterface;
ServiceConnection connection;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i = new Intent();
i.setAction("com.myapp.myservice.RemoteService");
startRemoteInterface(i);
bindRemoteInterface(i);
/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
/* Whereas this code does work. */
Button getMessage = (Button)findViewById(R.id.getMessage);
getMessage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String msg = null;
try {
msg = remoteInterface.getMessage();
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
class RemoteServiceConnection implements ServiceConnection{
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
remoteInterface = RemoteServiceInterface.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
}
private void startRemoteInterface(Intent i) {
startService(i);
}
private void bindRemoteInterface(Intent i) {
if(connection == null){
connection = new RemoteServiceConnection();
bindService(i, connection, Context.BIND_AUTO_CREATE);
} else {
Toast.makeText(getBaseContext(), "Service cannot bind - already bound.", Toast.LENGTH_SHORT).show();
}
}
}
Here is my remote service code:
package com.myapp.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
private final RemoteServiceInterface.Stub mBinder = new RemoteServiceInterface.Stub() {
#Override
public String getMessage() throws RemoteException {
return "Hello World!";
}
};
}
Here is my aidl file :
package com.myapp.myservice;
interface RemoteServiceInterface {
String getMessage();
}
Thanks in advance,
Rupesh
bindRemoteInterface(i);
/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
Please keep in mind that the bind is an asychronus call you have to wait for the callback in the ServiceConnection for onServiceConnected and perform actions after that.
Also you have to use the asInterface method to get the real interface for your connection this is demonstrated by the google aidl example
RemoteServiceInterface mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Following the example above for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service
mIRemoteService = RemoteServiceInterface.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
mIRemoteService = null;
}
};
You can then make the call on the mIRemoteService object. either directly in the onServiceConnected callback or by notifying the service.
remoteInterface is NULL before service is connected (onServiceConnected called) .
startService is an async call, you call startService don't mean the service is started and connected . when service is connected , onServiceConnected is called , then you can use the connection to call remote service .
Actually , you should always check weather remoteInterface is null or not .