上一次,我有讲到简单的service服务的一些简介以及对它的生命周期的研究,上次也有说到,服务是分为绑定和启动两大模块的,上次我们说了服务的启动,这次我们来说说服务的绑定
这一次的例子,我们将三个应用程序绑定到一个共同的服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 就用我们都知道的最为熟悉的QQ吧,我们都知道微信和QQ都是聊天软件,他们不是同一个开发团队开发的,但是QQ账号微信同样可以直接使用,可以得到QQ的所有信息(包括名字、账号、密码、头像、性别、年龄等等),针对这一现象,我们开始来写写代码做一个研究分享吧
首先,在XML页面设置两个编辑框,默认好我们模拟的QQ账户的密码和账户名,再设置一个登录按钮
<EditText
android:id="@+id/et_main_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="@+id/et_main_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="123456" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录"
android:onClick="login"
/>
然后再写一个QQUser类,里面设置四个账户属性,并且继承于Parcelable
public class QQUser implements Parcelable{
private String qqName;
private String qqPwd;
private String qqNumber;
private String qqSex;
public QQUser() {
}
public QQUser(String qqName, String qqPwd, String qqNumber, String qqSex) {
this.qqName = qqName;
this.qqPwd = qqPwd;
this.qqNumber = qqNumber;
this.qqSex = qqSex;
}
public String getQqName() {
return qqName;
}
public void setQqName(String qqName) {
this.qqName = qqName;
}
public String getQqPwd() {
return qqPwd;
}
public void setQqPwd(String qqPwd) {
this.qqPwd = qqPwd;
}
public String getQqNumber() {
return qqNumber;
}
public void setQqNumber(String qqNumber) {
this.qqNumber = qqNumber;
}
public String getQqSex() {
return qqSex;
}
public void setQqSex(String qqSex) {
this.qqSex = qqSex;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(qqName);
parcel.writeString(qqPwd);
parcel.writeString(qqNumber);
parcel.writeString(qqSex);
}
public static final Parcelable.Creator<QQUser> CREATOR=new Parcelable.Creator<QQUser>(){
@Override
public QQUser createFromParcel(Parcel parcel) {
QQUser qqUser=new QQUser();
qqUser.setQqName(parcel.readString());
qqUser.setQqPwd(parcel.readString());
qqUser.setQqNumber(parcel.readString());
qqUser.setQqSex(parcel.readString());
return qqUser;
}
@Override
public QQUser[] newArray(int i) {
return new QQUser[i];
}
};
}
接着,我们来写我们的服务,新建一个activity,让他继承Service,实现里面的Onbind方法,将应用程序和服务绑定,因为我们绑定的是一个对象(QQUser),所以其实我们可以自己写一个接口,使之更加方便简洁,在这里,我个人比较推荐用aidl,它相当于一个我们自己新建的interface,里面写一个登录的方法,这样我们在绑定服务的时候就可以直接使用了,代码如下:
// QQLoginInterfaceOut.aidl
package com.zking.g150831_android23_qq;
import com.zking.g150831_android23_qq.QQUser;
interface QQLoginInterfaceOut {
boolean login(String number,String pwd);
QQUser login2(in Map map);
}
public class QQLoginService extends Service {
class MyIBinder extends QQLoginInterfaceOut.Stub{
@Override
public boolean login(String number, String pwd) throws RemoteException {
if("10000".equals(number)&&"123456".equals(pwd)){
return true;
}
return false;
}
@Override
public QQUser login2(Map map) throws RemoteException {
String number=map.get("number").toString();
String pwd=map.get("pwd").toString();
if("10000".equals(number)&&"123456".equals(pwd)){
QQUser qqUser=new QQUser("卖女娃的小火柴",pwd,number,"不晓得");
return qqUser;
}
return null;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("test","onBind");
return new MyIBinder();
}
}
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pwd;
private Intent intent;
private QQLoginService.MyIBinder myIBinder;
private QQLoginInterface qqLoginInterface;
private QQLoginInterfaceOut qqLoginInterfaceOut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);
et_main_pwd = (EditText) findViewById(R.id.et_main_pwd);
intent = new Intent(this,QQLoginService.class);
}
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
Log.i("test","绑定成功了");
//myIBinder = (QQLoginService.MyIBinder) iBinder;
//qqLoginInterface = (QQLoginInterface) iBinder;
qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);
}
public void login(View view){
//获取用户名和密码
String number=et_main_number.getText().toString();
String pwd=et_main_pwd.getText().toString();
// boolean flag=myIBinder.login(number,pwd);
// boolean flag=qqLoginInterface.login(number,pwd);
boolean flag= false;
try {
// flag = qqLoginInterfaceOut.login(number,pwd);
Map map=new HashMap();
map.put("number",number);
map.put("pwd",pwd);
QQUser qqUser=qqLoginInterfaceOut.login2(map);
Toast.makeText(MainActivity.this, " "+qqUser.getQqName()+" "+qqUser.getQqSex(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
//判断
}
}
这样子,QQ应用程序,我们的准备
工作就做好了,接下来,我们来写微信端的代码,这边的代码相对而言就比较简洁许多,不用写登录,就可以直接引用QQ服务以及QQ里面的aidl文件,代码如下:
XML:和QQ一样(两个编辑框和一个登录按钮)
mainactivity:
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pwd;
private Intent intent;
private QQLoginInterfaceOut qqLoginInterfaceOut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);
et_main_pwd = (EditText) findViewById(R.id.et_main_pwd);
intent = new Intent();
ComponentName componentName=new ComponentName("com.zking.g150831_android23_qq","com.zking.g150831_android23_qq.QQLoginService");
intent.setComponent(componentName);
//显式Intent
//隐世Intent
}
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
qqLoginInterfaceOut = QQLoginInterfaceOut.Stub.asInterface(iBinder);
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);
}
public void login(View view){
String number=et_main_number.getText().toString();
String pwd=et_main_pwd.getText().toString();
try {
// boolean flag=qqLoginInterfaceOut.login(number,pwd);
Map map=new HashMap();
map.put("number",number);
map.put("pwd",pwd);
QQUser qqUser=qqLoginInterfaceOut.login2(map);
Toast.makeText(MainActivity.this, ""+qqUser.getQqName(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
最后将QQ里面的aidl整个包都拷贝过来,我们就可以用QQ账号来登录微信了,这样,我们就可以将两个应用程序只使用一个服务了