Binder instance is not being shared between processes.
Although Binder instance is static in MyUtil
class,
both app and service processes will have their own copies of MyUtil
code.
So, app process creates 1 static object for its MyUtil
class,
and service process creates another static object for its MyUtil
class.
Let's see it in action.
1. Running service in separate process
This is the AndroidManifest.xml.
<manifest
package="com.lakindu.staticobjectbehavior">
<application>
<service
android:name=".MyService"
android:process=":myservice" />
</application>
</manifest>
MyService.java
public class MyService extends Service {
private static final String TAG = "mytest_MyService";
private final IBinder mBinder = new IMyService.Stub() {
@Override
public void printHelloWorld() throws RemoteException {
Log.i(TAG, "This is just printing hello world");
MyUtil.printHelloWorld();
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
MyUtil.java
public class MyUtil {
private static final String TAG = "mytest_MyUtil";
private static final IBinder mMyBinder = new MyBinder();
public static void printHelloWorld() {
Log.i(TAG, "Just printing hello world from my util" + mMyBinder.toString());
}
}
MyBinder
is just a Binder, which logs a message every time it creates an object.
MyBinder.java
public class MyBinder extends Binder {
private static final String TAG = "mytest_MyBinder";
public MyBinder() {
Log.d(TAG, "Creating MyBinder object");
}
}
To test, I wrote this Android instrumented test.
app/src/androidTest/StaticObjectBehaviorTest.java
import org.junit.runner.RunWith;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import androidx.test.platform.app.InstrumentationRegistry;
@RunWith(AndroidJUnit4.class)
public class StaticObjectBehaviorTest {
@Rule
public final ServiceTestRule mServiceRule = new ServiceTestRule();
@Test
public void objectCreation() throws TimeoutException, RemoteException {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
// Calling MyUtil class in test app process.
MyUtil.printHelloWorld();
Intent intent = new Intent(appContext, MyService.class);
IBinder binder = mServiceRule.bindService(intent);
assertNotNull(binder);
IMyService myService = IMyService.Stub.asInterface(binder);
assertNotNull(myService);
// Using service proxy to call MyUtil class in service process.
myService.printHelloWorld();
}
}
Examining logs.
$ adb logcat | grep "mytest_"
[PID]
13054 D mytest_MyBinder: Creating MyBinder object
13054 I mytest_MyUtil: Just printing hello world from my utilcom.lakindu.staticobjectbehavior.MyBinder@5c24fc2
13089 I mytest_MyService: This is just printing hello world
13089 D mytest_MyBinder: Creating MyBinder object
13089 I mytest_MyUtil: Just printing hello world from my utilcom.lakindu.staticobjectbehavior.MyBinder@2723e12
As you can see there are 2 Binder objects being created for each process.
2. Running service in the same process
Just change the AndroidManifest.xml.
<manifest
package="com.lakindu.staticobjectbehavior">
<application>
<service
android:name=".MyService" />
</application>
</manifest>
No code changes.
Examining logs.
$ adb logcat | grep "mytest_"
[PID]
13202 D mytest_MyBinder: Creating MyBinder object
13202 I mytest_MyUtil: Just printing hello world from my utilcom.lakindu.staticobjectbehavior.MyBinder@5c24fc2
13202 I mytest_MyService: This is just printing hello world
13202 I mytest_MyUtil: Just printing hello world from my utilcom.lakindu.staticobjectbehavior.MyBinder@5c24fc2
When running in the same process, just one Binder instance is being created.