Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should onHandleIntent be called when IntentService is started with bindService?

My service extends IntentService and when it is started with startService, onHandleIntent gets called. However, when the service is started with bindService (I do need binding), onHandleIntent does not get called.

Should onHandleIntent be called when IntentService is started with bindService? Is startService the only way IntentService should be started?

The documentation for IntentService says the following:

Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

Currently I solve my problem by calling startService right after bindService but I find it ugly. I would like to know is there a way to make it work with just one call.

Code snippets follow, it might be that I am missing something obvious.

ExampleService.java

public class ExampleService extends IntentService {

private class IncomingHandler extends Handler {

    @Override
    public void handleMessage(Message message) {

        if (message.replyTo != null) {
            outMessenger = message.replyTo;
        }
    }
}

private Messenger messenger = new Messenger(new IncomingHandler()); 
private Messenger outMessenger = null;


public ExampleService() {
    super("ExampleService");
}

@Override
public IBinder onBind(Intent intent) {
    return messenger.getBinder();
}

@Override
protected void onHandleIntent(Intent arg0) {

    System.out.println("Service started");

    for (int i = 0; i < 5; i++) {

        SystemClock.sleep(5000);

        if (outMessenger != null) {
            try {
                outMessenger.send(Message.obtain());
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
}

Service Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.service"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
    android:minSdkVersion="3"
    android:targetSdkVersion="15" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/title_activity_main" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service android:name=".ExampleService">
        <intent-filter>
            <action android:name="com.example.service.ExampleService" />
        </intent-filter>
    </service>
</application>
</manifest>

MainActivity.java (caller)

public class MainActivity extends Activity implements ServiceConnection {


private class IncomingHandler extends Handler {

    @Override
    public void handleMessage(Message msg) {

        Toast.makeText(getApplicationContext(), "Message received", Toast.LENGTH_SHORT).show();
        System.out.println("Message received!");
        super.handleMessage(msg);
    }
}

private Messenger messenger = new Messenger(new IncomingHandler());

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

    Button button = (Button) findViewById(R.id.button1);
    button.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Intent intent = new Intent("com.example.service.ExampleService");
            bindService(intent, MainActivity.this, Context.BIND_AUTO_CREATE);
            //startService(intent);
        }
    });

}

@Override
public void onServiceConnected(ComponentName name, IBinder binder) {

    Message message = Message.obtain();
    message.replyTo = messenger;

    try {
        new Messenger(binder).send(message);
    } catch (RemoteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@Override
public void onServiceDisconnected(ComponentName name) {
    // TODO Auto-generated method stub
}
}
like image 244
Viktor Brešan Avatar asked Jan 15 '23 12:01

Viktor Brešan


1 Answers

Should onHandleIntent be called when IntentService is started with bindService?

No.

Is startService the only way IntentService should be started?

IMHO, yes. IMHO, IntentService is not designed for the binding pattern.

In your case, you can:

  • Pass a Messenger from the activity in an Intent extra in the command sent by startService(), or
  • Use LocalBroadcastManager, or
  • Use Otto, or
  • Use an ordered broadcast, if the IntentService might continue past the activity's life and you want to, say, display a Notification when the work gets done in that case,
  • Etc.
like image 200
CommonsWare Avatar answered Feb 08 '23 15:02

CommonsWare