不多说,直接上代码,博客最后有总结。
MainActivity.java
package com.xxx.xxx.validatedemo;
import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
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.widget.Button;
import android.widget.TextView;
import com.xxx.xxx.validatedemo.services.MyService;
import com.xxx.xxx.validatedemo.services.RemoteService;
public class MainActivity extends Activity implements View.OnClickListener
{
MyService myService;
IMyRemoteInterface myRemoteInterface;
ServiceConnection conn,remoteConn;
Button button,button2;
TextView textView,textview2;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
button.setOnClickListener(this);
button2=findViewById(R.id.button2);
button2.setOnClickListener(this);
textView=findViewById(R.id.text12);
textview2=findViewById(R.id.text13);
Intent serviceIntent = new Intent(this, MyService.class);
conn = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
MyService.MyBinder binder = (MyService.MyBinder) service;
myService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name)
{
myService = null;
}
};
getApplicationContext().bindService(serviceIntent, conn, Service.BIND_AUTO_CREATE);
Intent remoteIntent=new Intent(this,RemoteService.class);
remoteConn=new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
myRemoteInterface=IMyRemoteInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name)
{
}
};
this.bindService(remoteIntent,remoteConn,BIND_AUTO_CREATE);
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.button:
textView.setText(myService.getName());
break;
case R.id.button2:
try
{
textview2.setText(myRemoteInterface.getUserName());
} catch (RemoteException e)
{
e.printStackTrace();
}
break;
default:
break;
}
}
}
MyService.java
package com.xxx.xxx.validatedemo.services;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyService extends Service
{
private MyBinder binder = new MyBinder();
public MyService()
{
}
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public boolean onUnbind(Intent intent)
{
return super.onUnbind(intent);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent)
{
return this.binder;
}
public class MyBinder extends Binder
{
public MyService getService()
{
return MyService.this;
}
}
public String getName()
{
return "My Service";
}
@Override
public void onDestroy()
{
super.onDestroy();
}
}
RemoteService.java
package com.xxx.xxx.validatedemo.services;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.xxx.xxx.validatedemo.IMyRemoteInterface;
public class RemoteService extends Service
{
public RemoteService()
{
}
@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);
}
@Override
public IBinder onBind(Intent intent)
{
return new MyStub();
}
@Override
public void onCreate()
{
super.onCreate();
}
private class MyStub extends IMyRemoteInterface.Stub
{
@Override
public String getUserName() throws RemoteException
{
return "RemoteService";
}
}
}
IMyRemoteInterface.aidl
package com.xxx.xxx.validatedemo;
interface IMyRemoteInterface
{
String getUserName();
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xxx.xxx.validatedemo">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.xxx.xxx.validatedemo.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.xxx.xxx.validatedemo.services.MyService">
</service>
<service android:name="com.xxx.xxx.validatedemo.services.RemoteService"
android:process=":remote"
android:exported="false"
></service>
</application>
</manifest>
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button"
android:text="调用本地服务"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text12"
android:text="default"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/button2"
android:text="调用远程服务"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/text13"
android:text="default"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>
总结
核心函数就是bindService(Intent service, ServiceConnection conn,int flags)
- 首先调用serviceIntent中相关服务的onBind函数获取一个IBinder对象
- 这个对象会作为bindService函数中的ServiceConnection对象中重载的onServiceConnected(ComponentName name, IBinder service)函数中的IBinder参数service
- 如果onBind函数中返回的是Binder对象,那么可以根据这个Binder对象获取到对应的Service对象
- 如果onBind函数中返回的是Interface对应的Stub对象(也就是不同进程的服务),那么可以用Stub.asInterface函数获取对应的接口对象,然后调用对应的接口函数。
MyBinder和MyStub区别
- 内容不一样,MyBinder中定义的函数是自己写的,而MyStub中的是IMyRemoteInterface中定义好的
- 处理方法不一样 MyBinder是直接继承Binder类的,因此在OnServiceConnected的时候直接调用强制转换就可以。而MyStub因为涉及到aidl框架,所以一般使用对应Stub的asInterface函数来完成类型转换。
- 作用不一样,MyBinder的作用是获取service对象,从而使用其函数,而MyStub则是为了获取IMyRemoteInterface对象,从而使用被实现的函数。