一.简介
何为远程服务?
同一部手机里面的两个应用程序之间相互通信,被称为远程服务
把一个公共的模块给它提取出来,其他手机上面的所有应用程序去调用它。
远程服务两个特点:客户端,服务端
二.案例
远程服务:同一个手机里面两个应用程序之间,一个客户端(微信)一个服务端(QQ)
只要把QQ这个服务端搞定,客户端 微信就很简单了,重点在服务端。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
tools:context="com.zking.android24_myqq.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="MyQQ登录界面"
android:textSize="30sp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名:"
android:id="@+id/et_main_number"
/><!--number qq号-->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码:"
android:id="@+id/et_main_pass"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:onClick="login"
/>
</LinearLayout>
MyQQ1.0版本
MainActivity.java
package com.zking.android24_myqq;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);//qq号
et_main_pass = (EditText) findViewById(R.id.et_main_pass);//密码
}
public void login(View view){
String number=et_main_number.getText().toString();
String pass=et_main_pass.getText().toString();
if("766437357".equals(number) && "123456".equals(pass)){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}
}
MyQQ2.0版本(利用服务)
2.0版本:写一个服务类,专门用来进行QQ登录, 效果与QQ1.0版本一样但所用技术不同
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zking.android24_myqq">
<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=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--配置-->
<service android:name=".QQLoginService"
android:enabled="true"
android:exported="true"
>
</service>
</application>
</manifest>
MainActivity.java
package com.zking.android24_myqq;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pass;
private Intent intent;
private QQLoginService.MyIBinder myIBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);//qq号
et_main_pass = (EditText) findViewById(R.id.et_main_pass);//密码
intent = new Intent(this,QQLoginService.class);
}
//检测有没有连接成功
ServiceConnection connection= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//连接成功 IBinder强转为自己写的MyIBinder
Log.i("test","绑定成功");
myIBinder = (QQLoginService.MyIBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {//没有连接成功
Log.i("test","绑定失败");
}
};
//应用程序一启动就和服务绑定到一起去了
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);//Ctrl+P ServiceConnection服务连接 BIND_AUTO_CREATE在你绑定的时候自动创建(启动)服务
}
//点击登录
public void login(View view){
String number=et_main_number.getText().toString();
String pass=et_main_pass.getText().toString();
boolean flag=myIBinder.login(number,pass);//把账号和密码传给这个服务
if(flag){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}
}
QQLoginService.java
package com.zking.android24_myqq;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* 利用服务来进行登录
*
* QQ登录的服务
* 本地服务:启动服务的
* 远程服务:绑定服务 (应用程序一启动就和服务绑定到一起去了)
*
* Activity与服务进行通信
* 业务逻辑全部交给服务来写
*/
public class QQLoginService extends Service {
/**
* 自己写一个内部类
* MyIBinder把他想像成jspServlet里面的(业务逻辑类)Dao层,Dao方法
*/
class MyIBinder extends Binder{
//登录的方法
public boolean login(String number,String pass){
if("766437357".equals(number) && "123456".equals(pass)){
return true;
}else{
return false;
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {//远程服务一个onBind就够了 IBinder
Log.i("test","onBind");
return new MyIBinder();
}
}
效果图
MyQQ3.0版本(使用接口)
把2.0版本进行优化
3.0版本只是比2.0版本多了个接口的概念(实现类改为接口)
其他的类同2.0版本一样
接口和实现类里面的方法必须一模一样
MainActivity.java
package com.zking.android24_myqq;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pass;
private Intent intent;
//private QQLoginService.MyIBinder myIBinder; 不给自己的实现类了,给接口
private QQLogin qqlogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);//qq号
et_main_pass = (EditText) findViewById(R.id.et_main_pass);//密码
intent = new Intent(this,QQLoginService.class);
}
//检测有没有连接成功
ServiceConnection connection= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//连接成功 IBinder强转为自己写的MyIBinder
Log.i("test","绑定成功");
//myIBinder = (QQLoginService.MyIBinder) service;
qqlogin = (QQLogin) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {//没有连接成功
Log.i("test","绑定失败");
}
};
//应用程序一启动就和服务绑定到一起去了
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);//Ctrl+P ServiceConnection服务连接 BIND_AUTO_CREATE在你绑定的时候自动创建(启动)服务
}
//点击登录
public void login(View view){
String number=et_main_number.getText().toString();
String pass=et_main_pass.getText().toString();
//boolean flag=myIBinder.login(number,pass);//把账号和密码传给这个服务
boolean flag=qqlogin.login(number,pass);
if(flag){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}
}
QQLogin.java
package com.zking.android24_myqq;
/**
* QQ登录的接口
*/
public interface QQLogin {
public boolean login(String number, String pass);
}
QQLoginService.java
package com.zking.android24_myqq;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* 利用服务来进行登录
*
* QQ登录的服务
* 本地服务:启动服务的
* 远程服务:绑定服务 (应用程序一启动就和服务绑定到一起去了)
*
* Activity与服务进行通信
* 业务逻辑全部交给服务来写
*/
public class QQLoginService extends Service {
/**
* 自己写一个内部类
* MyIBinder把他想像成jspServlet里面的(业务逻辑类)Dao层,Dao方法
*/
class MyIBinder extends Binder implements QQLogin{//接口就要实现
//登录的方法
public boolean login(String number,String pass){
if("766437357".equals(number) && "123456".equals(pass)){
return true;
}else{
return false;
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {//远程服务一个onBind就够了 IBinder
Log.i("test","onBind");
return new MyIBinder();
}
}
MyQQ4.0版本(使用aidl)
AIDL:安卓接口定义语言
写aidl文件的目的是自动生成了一个接口,我们用这个自动生成的接口
为什么要用4.0版本,因为微信要用所以要用自动生成的那个aidl
MainActivity.java
package com.zking.android24_myqq;
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.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pass;
private Intent intent;
//private QQLoginService.MyIBinder myIBinder; 不给自己的实现类了,给接口
private QQLogin qqlogin;
private QQLoginInterface qqLoginInterface;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_number = (EditText) findViewById(R.id.et_main_number);//qq号
et_main_pass = (EditText) findViewById(R.id.et_main_pass);//密码
intent = new Intent(this,QQLoginService.class);
}
//检测有没有连接成功
ServiceConnection connection= new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//连接成功 IBinder强转为自己写的MyIBinder
Log.i("test","绑定成功");
//myIBinder = (QQLoginService.MyIBinder) service;
//qqlogin = (QQLogin) service;
qqLoginInterface = QQLoginInterface.Stub.asInterface(service);//给自动生成的.java文件(因为写了一个aidl文件,所以自动生成了一个.java文件)
}
@Override
public void onServiceDisconnected(ComponentName name) {//没有连接成功
Log.i("test","绑定失败");
}
};
//应用程序一启动就和服务绑定到一起去了
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);//Ctrl+P ServiceConnection服务连接 BIND_AUTO_CREATE在你绑定的时候自动创建(启动)服务
}
//点击登录
public void login(View view){
String number=et_main_number.getText().toString();
String pass=et_main_pass.getText().toString();
//boolean flag=myIBinder.login(number,pass);//把账号和密码传给这个服务
//boolean flag=qqlogin.login(number,pass);
boolean flag= false;
try {
flag = qqLoginInterface.login(number,pass);
} catch (RemoteException e) {
e.printStackTrace();
}
if(flag){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
}
}
QQLogin.java文件同上面一样
QQLoginService.java
package com.zking.android24_myqq;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
/**
* 利用服务来进行登录
*
* QQ登录的服务
* 本地服务:启动服务的
* 远程服务:绑定服务 (应用程序一启动就和服务绑定到一起去了)
*
* Activity与服务进行通信
* 业务逻辑全部交给服务来写
*/
public class QQLoginService extends Service {
/**
* 自己写一个内部类
* MyIBinder把他想像成jspServlet里面的(业务逻辑类)Dao层,Dao方法
*/
class MyIBinder extends QQLoginInterface.Stub{
@Override
public boolean login(String number, String pass) throws RemoteException {
if("766437357".equals(number) && "123456".equals(pass)){
return true;
}
return false;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {//远程服务一个onBind就够了 IBinder
Log.i("test","onBind");
return new MyIBinder();
}
}
QQLoginInterface.aidl
// QQLoginInterface.aidl
package com.zking.android24_myqq;
// Declare any non-default types here with import statements
interface QQLoginInterface {
boolean login(String number, String pass);//把接口QQLogin的方法copy过来,但是不要修饰符
}
效果图
最后,MyWeChat(微信客户端)
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical"
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="com.zking.android24_mywechat.MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="MyWeChat"
android:textSize="30sp"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名:"
android:id="@+id/et_main_number"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码:"
android:id="@+id/et_main_pass"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录"
android:onClick="login"
/>
</LinearLayout>
MainActivity.java
package com.zking.android24_mywechat;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.zking.android24_myqq.QQLoginInterface;
/**
* 服务是写在QQ里面的,要启动QQ的服务
* 通过微信里面怎么启动qq的服务
* Android 5.0 之后,启动其他应用程序的服务,不允许使用隐式
*
*
* 把QQ自动生成的那个类copy到微信里面去
*/
public class MainActivity extends AppCompatActivity {
private EditText et_main_number;
private EditText et_main_pass;
private Intent intent;
private QQLoginInterface qqLoginInterface;
@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_pass = (EditText) findViewById(R.id.et_main_pass);
intent = new Intent();
ComponentName componentName=new ComponentName("com.zking.android24_myqq","com.zking.android24_myqq.QQLoginService");//你要启动的服务(QQ)所在的包名,QQ里面的服务类(1.应用程序的包名)
intent.setComponent(componentName);
}
//连接对象
ServiceConnection connection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
qqLoginInterface = QQLoginInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onResume() {
super.onResume();
//绑定服务
bindService(intent,connection, Service.BIND_AUTO_CREATE);//2连接对象
}
public void login(View view){
String number=et_main_number.getText().toString();
String pass=et_main_pass.getText().toString();
try {
boolean b=qqLoginInterface.login(number,pass);
if(b){
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "登录失败", Toast.LENGTH_SHORT).show();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}