Android专题8——本地服务和远程服务通信

关于远程服务

  • 远程服务指的是服务和访问者不在同一个应用程序中,即不在同一个进程中。

  • 访问远程服务类似进程间通信。

  • 访问者和远程服务需要遵守能够被操作系统理解的协议,AIDL。

1. 在服务端和客户端配置AIDL

  • aidl文件最好都放在aidl目录下,aidl文件用于接口描述

  • 会自动生成一个同名的JAVA文件

  • 在自动生成的JAVA文件中,系统会自动定义一个Stub类,继承Binder类,实现aidl文件中描述的接口

2. 编写service业务代码

  • 在清单文件中注册

  • 实现自定义的IBinder

        <service android:name=".StudentService">
            <intent-filter >
                <action android:name="com.njulya.REMOTESERVICE"/>
            </intent-filter>
        </service>

import com.njulya.aidl.StudentQuery;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class StudentService extends Service {
    IBinder iBinder;
    String[] names = {"张阳","李永安","潘杰"};
    @Override
    public IBinder onBind(Intent intent) {
        iBinder = new StudentBinder();
        return iBinder;
    }
/**
 * 实现IBinder接口,用于通信
 * @author Andy
 */
    private class StudentBinder extends StudentQuery.Stub{
        @Override
        //aidl文件中描述的接口
        public String query(int no) throws RemoteException {
            return names[no-1];//业务代码
        }

    }
}

3.编写客户端应用

package com.njulya.remoteserviceclient;

import com.njulya.aidl.StudentQuery;

import android.app.Activity;
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.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    private EditText studentId;
    private TextView content;
    private StudentQuery studentQuery;
    private ServiceConnection conn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        studentId = (EditText)this.findViewById(R.id.student_id);
        content = (TextView)this.findViewById(R.id.content);
        conn = new StudentConnetion();
        Intent service = new Intent("com.njulya.REMOTESERVICE");
        this.bindService(service, conn, BIND_AUTO_CREATE);
    }
    /**
     * 按键触发业务代码
     * @param v
     */
    public void queryOnClick(View v){
        int no = Integer.valueOf(studentId.getText().toString());
        try {
            String studentName = studentQuery.query(no);
            content.setText(studentName);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    private class StudentConnetion implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //将IBinder代理对象转换为接口类型
            studentQuery = StudentQuery.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            studentQuery = null;
        }
    }

    @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

关于本地服务

  • 启动的service是运行在主线程中的,所以耗时的操作还是要新建工作线程

  • 用bindService时需要实现ServiceConnection,flags用BIND_AUTO_CREATE

  • service中关键要返回IBinder的实现类对象,该对象中会使用服务中的一些API

  • 一般在自定义的ServiceConnection实现类中得到和关闭IBinder对象

  • 通过得到的IBinder对象实现调用服务中的API

业务界面

客户端代码

package com.njulya.intsum;

import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    private EditText num1;
    private EditText num2;
    private TextView sum;
    private ServiceConnection conn;

    //自定义的公共接口,用于求两数之和
    private SumOfTwo sumOfTwo;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        num1 = (EditText)this.findViewById(R.id.num1);
        num2 = (EditText)this.findViewById(R.id.num2);
        sum = (TextView)this.findViewById(R.id.sum);
        Button button = (Button)this.findViewById(R.id.button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                sum();
            }
        });
        conn = new SumConnetion();
        Intent service = new Intent(this, SumService.class);
        this.bindService(service, conn, BIND_AUTO_CREATE);
    }

    protected void sum() {
        int number1 = Integer.valueOf(num1.getText().toString());
        int number2 = Integer.valueOf(num2.getText().toString());
        int result = sumOfTwo.sum(number1, number2);
        sum.setText(String.valueOf(result));

    }
    private class SumConnetion implements ServiceConnection{
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            sumOfTwo = (SumOfTwo)service;
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            sumOfTwo = null;
        }
    }

    @Override
    protected void onDestroy() {
        unbindService(conn);
        super.onDestroy();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

服务端代码

package com.njulya.intsum;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class SumService extends Service {

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return new SumBinder();
    }
    public class SumBinder extends Binder implements SumOfTwo{
        @Override
        public int sum(int number1, int number2) {
            return number1 + number2;
        }

    }
}

时间: 2024-08-14 16:34:47

Android专题8——本地服务和远程服务通信的相关文章

Android:(本地、可通信的、前台、远程)Service使用全面介绍

前言 Service作为Android四大组件之一,应用非常广泛 本文将介绍Service最基础的知识:Service的生命周期 如果你对Service还未了解,建议先阅读我写的文章: Android四大组件:Service史上最全面解析 目录 1. Service分类 1.1 Service的类型 1.2 特点 2.具体使用解析 2.1 本地Service 这是最普通.最常用的后台服务Service. 2.1.1 使用步骤 步骤1:新建子类继承Service类 需重写父类的onCreate()

Android Service学习之本地服务

Service是在一段不定的时间运行在后台,不和用户交互应用组件.每个Service必须在manifest中 通过来声明.可以通过contect.startservice和contect.bindserverice来启动. Service和其他的应用组件一样,运行在进程的主线程中.这就是说如果service需要很多耗时或者阻塞的操作,需要在其子线程中实现. service的两种模式(startService()/bindService()不是完全分离的): 本地服务 Local Service

Android Binder机制(3) 本地服务注册过程

本博客将讲解本地服务的注册过程,为了方便大家更好地理解,选择了MediaPlayer Service作为例子. 启动并注册MediaPlayer Service的代码在frameworks/base/media/mediaserver/main_mediaserver.cpp中,如下: main_mediaserver.cpp 1 2 3 4 5 6 7 8 9 10 11 12 int main(int argc, char** argv) { sp<ProcessState>proc(Pr

LoadRunner+Android模所器实现抓包并调试本地服务端

步骤就是 1:新建LR脚本.协议选择Mobile Application - HTTP/HTML 2:在record里选择第三个:Record Emulator........ 3:  选择下一步后,在emulator to record选择模拟器tools目录下的emulator.exe                     command line 里输入avd虚拟机的名称:用@连接  如@test      working directory 随便选个路径就行了 4:然后运行,就会自动启

Android客户端与本地服务器Socket通信

Android客户端与本地服务器Socket通信 Socket服务器运行结果图?? 一.客户端和服务器端的选择: 客户端是我们手机端,关于服务器端,只要安装了JDK,自然就拥有通讯的功能,我们只需要在Eclipse或者MyEclipse中写好文章中服务器端的代码,运行起来即可,用accept()方法启动服务器端,等待客户端的连接,在未连接的情况下,服务器端处于堵塞的状态. 二.客户端注意事项 andriod客户端添加网络访问权限 <uses-permission android:name="

Android客户端与PHP服务端通信(二)

概述 本节通过一个简单的demo程序简单的介绍Android客户端通过JSON向PHP服务端提交订单,PHP服务端处理订单后,通过JSON返回结果给Android客户端.正常来讲,PHP服务端在处理订单过程中,需要与MySQL数据库交互,这里为了简单起见,暂时省掉MySQL. 通信格式 首先,需要定下客户端与服务端之间通信格式,如下表 Android客户端 客户端与服务端采用JSON数据格式通信,同时采用HTTP通信协议交互,采用POST方式提交结果.同时还要注意一点,与WEB服务器通信的过程需

Android Service 后台服务之本地服务

Service是Android系统的服务组件,适用于开发没有用户界面且长时间在后台运行的功能 - Service简介 因为手机硬件性能和屏幕尺寸的限制,通常Android系统仅允许一个应用程序处于激活状态并显示在手机屏幕上,而暂停其他处于未激活状态的程序. 因此,Android系统需要一种后台服务机制,允许在没有用户界面的情况下,使程序能够长时间在后台运行,实现应用程序的后台服务功能. 在实际应用中,有很多应用需要使用Service,比如MP3播放器要求在关闭播放器界面后,仍然能够后台保持音乐持

Android客户端与PHP服务端通信(四)---极光推送示例工程分析

概述 上一节,描述了注册极光推送并使用其例子的方法,这一节准备研究一下示例工程的框架,为移植它做准备. 分析例程源码 首先分析一下例程的源码结构,建议对照着JPUSH的官方文档(http://docs.jpush.io/)分析,我就是这样做的. 注册应用后,下载的示例工程结构如下, ExampleApplication.java:该类为应用程序定制了一个Application类,因为调用JPush的SDK时,需要调用JPush提供的init()函数API,而按照官方文档的说明"init 只需要在

Android 四大组件 Service 服务

1.Service简介 按照使用范围分类: 类别 优点 缺点 区别 应用 本地服务 Local  Service 本地服务在一定程度上节约了资源,另外本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL.相应bindService会方便很多. 主进程被Kill后,服务便会终止. 本地服务依附在主进程上,而不是独立的进程,用于应用程序内部 . 音乐播放服务 远程服务 Remote Service 对应进程名格式为所在包名加上指定的android:process字符串.由于是独立的进程,因此