Android中的服务(service)详解(三)--远程服务(remote)

1. 引言:

(1)AIDL的作用

在Android平台,每个应用程序都是一个单独的JVM,都运行在自己的进程空间里, 通常,一个进程不允许访问另一个进程的内存空间(一个应用不能访问另一个应用)。当用户(程序开发人员)想在一个App中访问另一个App的进程空间的时候,就需要进程间通信。在Android中,远程服务为我们提供了实现进程间通信的方式,其中,AIDL是应用程序开发人员常的一种方式。

AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码。如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参 数。换句比较浅显的话来说,就是我这个App应用的activity,需要调用其他App应用的Service.当然同一App应用的activity
与service也可以在不同进程间,这可以设置Service配置中,android:process=":remote"。

可以看出,aidl的适用场景为: 只有你允许客户端从不同的应用程序为了进程间的通信而去访问你的service时,你可以使用AIDl来实现。例如,百度地图给我们提供了下面的service:com.baidu.location.f,我们只要在我们的应用程序的manifest.xml文件中声明这个service,就能用它提供的服务了。:

<service

android:name="com.baidu.location.f"

android:enabled="true"

android:process=":remote" >

</service>

2. 本篇主要实例:

应用服务之远程(remote)服务的开启和运用,也就是AIDL的创建和使用过程:

  例子说明:

(1). 功能: 创建remote service,在service中计算出指定路径下有多少个文件,并在UI显示。

(2). 您将学到: a. remote service的定义和使用;

b. Aidl文件的定义和使用。

创建过程:

(1)在工程的src下,新建立一个文本文件,将要实现的函数放在这个文件中,后缀为.aidl。

(2)刷新工程后,就会发现在gen包下,有一个同名的java文件,这是aidl工具自动生成的,里面,就有我们要实现的函数。

(3)Aidl定义好后,我们就要实现我们的remote service了。它也是继承自service的。

(4)Service实现后,要将它在mainfest.xml设置为remote.注意,客户端服务端在同个App中,android:process=":remote",代表在应用程序里,当需要该service时,会自动创建新的进程。而如果是android:process="remote",没有“:”分号的,则创建全局进程,不同的应用程序共享该进程。

(5)最后,来实现我们的客户端,也就是Activity,来调用service。

3. 例子代码:

(1).aidl文件:IFileCountService.aidl:

package com.example.remoteservicetest;

interface IFileCountService{

int getFileCnt(String path);

}

(2). remote service的实现:MyRemoteService.java:

package com.example.remoteservicetest;

import java.io.File;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

public class MyRemoteService extends Service {

static final String TAG="MyService";

private int fileCnt = 0;

//定义内部类MyRemoteServiceImpl,继承我们的AIDL文件自动生成的内部类,

//并且实现我们AIDL文件定义的接口方法

private class MyRemoteServiceImpl extends IFileCountService.Stub{

@Override

public int getFileCnt(String path) throws RemoteException {

Log.e(TAG, "path");

File file = new File(path);

if (file.exists()) {

if (file.isDirectory()) {

File files[] = file.listFiles();

if (files == null ) {

return 0;

}

for (int i = 0; i < files.length; i++) {

if (files[i].isFile()) {

fileCnt++;

}

}

}

}

return fileCnt;

}

}

@Override

public IBinder onBind(Intent arg0) {

//返回AIDL实现

return new MyRemoteServiceImpl();

}

@Override

public void onDestroy(){

Log.e(TAG, "Release MyService");

super.onDestroy();

}

}

  (3). 客户端Activity:AndroidRemoteActivity.java:

package com.example.androidservicetest;

import com.example.remoteservicetest.IFileCountService;

import com.example.remoteservicetest.MyRemoteService;

import android.app.Activity;

import android.content.ComponentName;

import android.content.Context;

import android.content.Intent;

import android.content.ServiceConnection;

import android.os.Bundle;

import android.os.IBinder;

import android.os.RemoteException;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

public class AndroidRemoteActivity extends Activity {

static final String TAG="AndroidRemoteActivity";

int fileCnt = 0;

private TextView textView;

Button btn1;

Button btn2;

@Override

public void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

textView = (TextView)findViewById(R.id.textview);

btn1 = (Button)findViewById(R.id.button1);

btn2 = (Button)findViewById(R.id.button2);

btn2.setVisibility(View.GONE);

btn1.setText("Get File Count:");

if(btn1!=null)

btn1.setOnClickListener(new OnClickListener(){

@Override

public void onClick(View v) {

//绑定一个服务

fileCnt = 0;

bindService();

}

});

}

IFileCountService iService=null;

private ServiceConnection  conn=new ServiceConnection(){

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

//返回AIDL接口对象,然后可以调用AIDL方法

iService=IFileCountService.Stub.asInterface(service);

try {

fileCnt=iService.getFileCnt("/sdcard");

}

catch (RemoteException e) {

Log.e(TAG,"error 000");

e.printStackTrace();

}

Log.e(TAG, "file count:"+fileCnt);

textView.setText("file count:"+fileCnt);

}

@Override

public void onServiceDisconnected(ComponentName name) {

Log.i(TAG, "onServiceDisconnected");

}

};

private void bindService(){

Intent intent=new Intent(this,MyRemoteService.class);

startService(intent);

bindService(intent, conn, Context.BIND_AUTO_CREATE);

}

}

(4). AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.example.androidservicetest"

android:versionCode="1"

android:versionName="1.0" >

<uses-sdk

android:minSdkVersion="8"

android:targetSdkVersion="18" />

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

<activity

android:name="com.example.androidservicetest.MainActivity"

android:label="@string/app_name" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity

android:name="com.example.androidservicetest.AndroidLocalServiceActivity" >

</activity>

<activity

android:name="com.example.androidservicetest.AndroidRemoteActivity" >

</activity>

<service android:name="com.example.androidservicetest.PackageFindService" >

<intent-filter>

<action android:name="com.test.service"/>

</intent-filter>

</service>

<service android:name="com.example.remoteservicetest.MyRemoteService"

android:process=":remote"

>

<intent-filter>

<action android:name="com.example.remoteservicetest.IFileCountService"/>

</intent-filter>

</service>

</application>

</manifest>

4. 测试结果:

运行程序后,会显示两个button,第一个是测试locel service的,第二个是测试remote service的,点第二个,再点,就会在屏幕上显示sdcard根目录的文件个数了。

5. 代码下载:

http://download.csdn.net/detail/liranke/8401933

时间: 2024-10-17 20:30:48

Android中的服务(service)详解(三)--远程服务(remote)的相关文章

Android 四大组件之Service详解

                   Android四大组件之Service详解    来这实习已经10多天了,今天整理整理学习时的Android笔记.正所谓好记性不如烂笔头,今天来说说service组件. service可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的. Service是在一段不定的时间运行在后台,不和用户交互应用组件.每个

Android中图片压缩方案详解

如感觉排版不舒服,可移步至此处查看 图片的展示可以说在我们任何一个应用中都避免不了,可是大量的图片就会出现很多的问题,比如加载大图片或者多图时的OOM问题,可以移步到Android高效加载大图.多图避免程序OOM.还有一个问题就是图片的上传下载问题,往往我们都喜欢图片既清楚又占的内存小,也就是尽可能少的耗费我们的流量,这就是我今天所要讲述的问题:图片的压缩方案的详解. 1.质量压缩法 设置bitmap options属性,降低图片的质量,像素不会减少 第一个参数为需要压缩的bitmap图片对象,

Android中CursorAdapter的使用详解

一.CursorAdapter介绍 CursorAdapter这个类是继承于BaseAdapter的它是一个虚类它为Cursor和ListView连接提供了桥梁 二.CursorAdapter详解 1.CursorAdapter的继承关系图 从图中可以看出CursorAdapter是继承于BaseAdapter的,它有一个直接的子类SimpleCursorAdapter 2.CursorAdapter的用法 我们首先看一下CursorAdapter的部分源码: /** * @see androi

Android逆向之旅---Android中的sharedUserId属性详解

一.前言 今天我们来看一下Android中一个众人熟悉的一个属性:shareUserId,关于这个属性可能大家都很熟悉了,最近在开发项目,用到了这个属性,虽然知道一点知识,但是感觉还是有些迷糊,所以就写篇文章来深入研究一下. 关于Android中的sharedUserId的概念这里就简单介绍一下: Android给每个APK进程分配一个单独的空间,manifest中的userid就是对应一个分配的Linux用户ID,并且为它创建一个沙箱,以防止影 响其他应用程序(或者其他应用程序影响它).用户I

Android中Canvas绘图基础详解(附源码下载)

Android中,如果我们想绘制复杂的自定义View或游戏,我们就需要熟悉绘图API.Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形.Canvas绘图有三个基本要素:Canvas.绘图坐标系以及Paint.Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint.drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状

Android中Canvas绘图基础详解

原文:http://blog.csdn.net/iispring/article/details/49770651 Android中,如果我们想绘制复杂的自定义View或游戏,我们就需要熟悉绘图API.Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形.Canvas绘图有三个基本要素:Canvas.绘图坐标系以及Paint.Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要

Android中Activity启动模式详解,可以控制程序按home键后进来还会调用一个自己不喜欢的界面

其实这是很简单的一个问题.但是这还是要对android中activity的启动模式有相当的理解才行,当点击home键的时候,懂Android的人都知道,他会把当前activity放到后退栈中, 栈(Stack)又称堆栈,它是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算.人们把此端称为栈顶,栈顶的第一个元素被称为栈顶元素,相对地,把另一端称为栈底.向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使之成为新的栈顶元素:从一个栈删除元素又称为出栈或退栈,它是把栈

android中include标签使用详解

android中include标签是为了便于控件的覆用的一个很好解决方案. 但是也有一些需要注意的地方,下面是本人在项目中碰到过的一个问题,做此记录,便于以后查看. include标签用法. 1.新建一个xml文件,命名 head.xml head.xml文件内容如下: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.

Android 中的消息传递,详解广播机制

--------------------------------------广播机制简介--------------------------------------------- Android中的广播机制非常灵活,Android中的每个应用程序都可以对自己感兴趣的广播进行注册,这个程序也只会收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的. Android提供了一套完整的API,允许应用程序自由地发送和接受广播. Android中的广播主要可以分为两种类型,标

Android中Activity启动模式详解

在Android中每个界面都是一个Activity,切换界面操作其实是多个不同Activity之间的实例化操作.在Android中Activity的启动模式决定了Activity的启动运行方式. Android总Activity的启动模式分为四种: Activity启动模式设置: <activity android:name=".MainActivity" android:launchMode="standard" /> Activity的四种启动模式: