Pearman
Pearman

Reputation: 1068

Android bindService() returns false when using AIDL?

For some reason I cannot bind to my service? I need the onServiceConnected() method to run so that I can use my AIDL interface. What am I doing wrong?

private ServiceConnection serviceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        Log.d("BindingService", "Service trying to bind!");
        sendService = ISendMessageService.Stub.asInterface((IBinder) service);
        boundToService = true;
        pendingFragment.bindToService();
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        sendService = null;
        boundToService = false;
        pendingFragment.unbindService();
    }
};

The main activity methods:

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

    schedulerFragment = new SchedulerFragment();
    pendingFragment = new PendingFragment();

    fm = getFragmentManager();

    titleBar = getActionBar();
    titleBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    scheduleTab = titleBar.newTab();
    pendingTab = titleBar.newTab();

    scheduleTab.setText("Schedule");
    pendingTab.setText("Pending");

    scheduleTab.setTabListener(new MyTabListener(schedulerFragment));
    pendingTab.setTabListener(new MyTabListener(pendingFragment));

    titleBar.addTab(scheduleTab);
    titleBar.addTab(pendingTab);

    titleBar.selectTab(scheduleTab);

    Boolean success = getApplicationContext().bindService(new Intent(SendMessageService.class.getName()),
            serviceConnection, Context.BIND_AUTO_CREATE);
    Log.d("ServiceConnection", success.toString());
}
@Override
public void onStop() {
    super.onStop();
    if (boundToService) {
        unbindService(serviceConnection);
    }
}

@Override
public void onPause() {
    super.onPause();
    if (boundToService) {
        unbindService(serviceConnection);
    }
}

This is the service's onBind() function:

@Override
public IBinder onBind(Intent intent) {
    mBinder =  new ISendMessageService.Stub(){

        @Override
        public void deleteMessage(int index) throws RemoteException {
            TimedMessage m = schedule.get(index);
            schedule.get(index).alarm.cancel(m.intent);
            schedule.remove(m);
        }

        @Override
        public void cancelAllMessages() throws RemoteException {
            for(TimedMessage m : schedule){
                m.alarm.cancel(m.intent);
            }
            schedule.clear();
        }

    };
    return mBinder;

The manifest:

<service
        android:name="com.pearhill.messagesender.SendMessageService"
        android:enabled="true"
        android:exported="true"
        android:process=":remote" >
        <intent-filter>
            <action android:name="com.pearhill.messagesender.ISendMessageService.aidl" />
        </intent-filter>
    </service>

Upvotes: 2

Views: 2559

Answers (1)

sgupta
sgupta

Reputation: 565

Here are the links for full description:

https://developer.android.com/guide/components/bound-services.html

https://developer.android.com/guide/components/aidl.html#Calling

  1. As a key point make sure your aidl is copied over to your application properly. Clean the project and remove aidl.
  2. Then copy the aidl over to your application in aidl folder, but package name same of remote aidl. Rebuild. You need not to mention service in your androidManifest of calling application; it will be taken care by aidl interface that you copied over.
  3. Make sure service is also an app and not a library (jar type). At least we couldn't make it work with service in jar file. You may choose "No activity" in the new app wizard, if you are not planning to create local activity. In that case you can create apk using "Build->Build Apk" menu in Android studio for service based app. Make sure to install the service apk before running BindService from remote app. You need not to run service as BindService will also start the service, but you need to install apk, so that it is available in system. You can use adb install path/myapkname.apk.
  4. Action name is not must, but this is how we did bind the service, where "com.example.RemoteService.BIND" was action name for service:

    String pkg = IRemoteService.class.getPackage().getName();
                //get the class name from the interface package
                String interfaceName = IRemoteService.class.getName();
                String clsName = interfaceName.replace("IRemoteService", "RemoteService");
    Intent it = new Intent("com.example.RemoteService.BIND");
                    it.setClassName(pkg, clsName);
                    boolean bRet = getApplicationContext().bindService(it, mConnection, Service.BIND_AUTO_CREATE);
                    Log.d("IRemote", "IRemoteService Service.BIND_AUTO_CREATE return: " + bRet);
    

    This is what was used in eclipse and worked, but failed in Android studio because of explicit intent:

        Intent it = new Intent( );
        it.setClassName("com.example.aidlservice",
         "com.example.aidlservice.MyService");
        //optional
        it.setAction("com.example.RemoteService.BIND");
        //binding to remote service
        boolean bRet = bindService(it, mServiceConnection, Service.BIND_AUTO_CREATE);
        Log.d("IRemote", "Service.BIND_AUTO_CREATE");
    

Here is manifest of service app. You may want to add permissions for security reasons:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testaidl">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <service android:name=".RemoteService" android:process=":remote" android:exported="true">
            <intent-filter>
                <action android:name="com.example.RemoteService.BIND" />
            </intent-filter>
        </service>
    </application>

</manifest>

Upvotes: 2

Related Questions