详解Android 进程间通信的几种实现方式

一、概述

由于应用程序之间不能共享内存。在不同应用程序之间交互数据(跨进程通讯),在Android SDK中提供了4种用于跨进程通讯的方式。

这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。

 Activity

Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。

在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。

Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" );
startActivity(callIntent);

Content Provider 

Android应用程序可以使用文件或SqlLite数据库来存储数据。Content Provider提供了一种在多个应用程序之间数据共享的方式(跨进程共享数据)。应用程序可以利用Content Provider完成下面的工作

1. 查询数据

2. 修改数据

3. 添加数据

4. 删除数据

虽然Content Provider也可以在同一个应用程序中被访问,但这么做并没有什么意义。Content Provider存在的目的向其他应用程序共享数据和允许其他应用程序对数据进行增、删、改操作。

Android系统本身提供了很多Content Provider,例如,音频、视频、联系人信息等等。我们可以通过这些Content Provider获得相关信息的列表。这些列表数据将以Cursor对象返回。因此,从Content Provider返回的数据是二维表的形式。

广播(Broadcast) 

广播是一种被动跨进程通讯的方式。当某个程序向系统发送广播时,其他的应用程序只能被动地接收广播数据。这就象电台进行广播一样,听众只能被动地收听,而不能主动与电台进行沟通。
在应用程序中发送广播比较简单。只需要调用sendBroadcast方法即可。该方法需要一个Intent对象。通过Intent对象可以发送需要广播的数据。

Service

1.利用AIDL Service实现跨进程通信

这是我个人比较推崇的方式,因为它相比Broadcast而言,虽然实现上稍微麻烦了一点,但是它的优势就是不会像广播那样在手机中的广播较多时会有明显的时延,甚至有广播发送不成功的情况出现。

注意普通的Service并不能实现跨进程操作,实际上普通的Service和它所在的应用处于同一个进程中,而且它也不会专门开一条新的线程,因此如果在普通的Service中实现在耗时的任务,需要新开线程。

要实现跨进程通信,需要借助AIDL(Android Interface Definition Language)。Android中的跨进程服务其实是采用C/S的架构,因而AIDL的目的就是实现通信接口。

首先举一个简单的栗子。

服务端代码如下:

首先是aidl的代码:

package com.android.service; 

interface IData
{
  int getRoomNum();
}

RoomService的代码如下:

package com.android.service; 

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

public class RoomService extends Service{ 

  private IData.Stub mBinder=new IData.Stub() { 

    @Override
    public int getRoomNum() throws RemoteException {
       return 3008;
    }
  }; 

  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  } 

}

AndroidManifest如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.android.aidlsampleservice"
  android:versionCode="1"
  android:versionName="1.0" > 

  <uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="17" /> 

  <application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    <service android:name="com.android.service.RoomService">
      <intent-filter>
        <action android:name="com.aidl.service.room"/>
      </intent-filter>
    </service>
  </application> 

</manifest>

然后运行该Service所在的Project即可。

客户端代码如下:

注意客户端也要有aidl文件,所以最简单的办法就是将Service端中aidl所在的包直接复制过去。另外要注意的是在onDestroy中要解除和Service的绑定。

MainActivity.java的代码如下:

package com.example.aidlsampleclient; 

import com.android.service.IData; 

import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.widget.Button;
import android.widget.Toast;
import android.view.View; 

public class MainActivity extends Activity implements View.OnClickListener{ 

  private static final String TAG="MainActivity";
  private static final String ROOM_SERVICE_ACTION="com.aidl.service.room"; 

  private Button bindServiceButton;
  private Button getServiceButton; 

  IData mData; 

  private ServiceConnection conn=new ServiceConnection()
  { 

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) { 

      Log.i(TAG,"----------------onServiceConnected--------");
      mData=IData.Stub.asInterface(service);
    } 

    @Override
    public void onServiceDisconnected(ComponentName name) { 

      Log.i(TAG,"----------------onServiceDisconnected-------------");
      mData=null; 

    } 

  }; 

  private void initView()
  {
    bindServiceButton=(Button)findViewById(R.id.bindServiceButton);
    getServiceButton=(Button)findViewById(R.id.getServiceButton);
    bindServiceButton.setOnClickListener(this);
    getServiceButton.setOnClickListener(this);
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  } 

  @Override
  public void onClick(View v) {
   switch(v.getId())
    {
    case R.id.bindServiceButton:
      bindService();
      break;
    case R.id.getServiceButton:
      getService();
       break;
    default:
       break;
    }
  } 

  private void bindService()
  {
    Intent intent=new Intent();
    intent.setAction(ROOM_SERVICE_ACTION);
    bindService(intent,conn,BIND_AUTO_CREATE);
  } 

  private void getService()
  {
    try
    {
      if(mData!=null)
      {
        int roomNum=mData.getRoomNum();
        showLongToast("RoomNum:"+roomNum);
      } 

    }
    catch(RemoteException ex)
    {
      ex.printStackTrace();
    } 

  } 

  private void showLongToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
  } 

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(conn);
  }
}

activity_main.xml的代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context=".MainActivity" > 

  <Button
    android:id="@+id/bindServiceButton"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="BindService"
    />
  <Button
    android:id="@+id/getServiceButton"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="GetService"
    android:layout_below="@id/bindServiceButton"
    />
</RelativeLayout>

运行结果如下:

然后举一个稍微复杂一点的栗子,注意如果*.aidl文件中含有自定义的对象,那么该对象的类要实现Parcelable接口,并且要新建一个该类的aidl文件,否则会出现could not find import for class com.android.service.XX的错误,其中XX为类名。还是上面的栗子,但是aidl文件中添加了一些新的方法。仍以上面的RoomService为例,

Service端的代码如下:

Room类的代码为:

package com.android.service; 

import android.os.Parcel;
import android.os.Parcelable; 

public class Room implements Parcelable{ 

  //房间号
  private int roomNum;
  //房间大小
  private float roomSpace;
  //是否有空调
  private boolean hasAirConditioner;
  //是否有Wifi
  private boolean hasWifi;
  //房间内的装饰风格
  private String decorativeStyle; 

  public static final Parcelable.Creator<Room>CREATOR=new Parcelable.Creator<Room>() { 

    @Override
    public Room createFromParcel(Parcel source) {
      return new Room(source);
    } 

    @Override
    public Room[] newArray(int size) {
      return null;
    } 

  }; 

  public Room(int roomNum,float roomSpace,boolean hasAirConditioner,boolean hasWifi,String decorativeStyle)
  {
    this.roomNum=roomNum;
    this.roomSpace=roomSpace;
    this.hasAirConditioner=hasAirConditioner;
    this.hasWifi=hasWifi;
    this.decorativeStyle=decorativeStyle;
  } 

  private Room(Parcel source)
  {
    roomNum=source.readInt();
    roomSpace=source.readFloat();
    boolean[]tempArray=new boolean[2];
    source.readBooleanArray(tempArray);
    hasAirConditioner=tempArray[0];
    hasWifi=tempArray[1];
    decorativeStyle=source.readString();
  } 

  @Override
  public String toString()
  {
    StringBuilder sb=new StringBuilder();
    sb.append("Basic info of room is as follows:\n");
    sb.append("RoomNum:"+roomNum+"\n");
    sb.append("RoomSpace:"+roomSpace+"\n");
    sb.append("HasAirConditioner:"+hasAirConditioner+"\n");
    sb.append("HasWifi:"+hasWifi+"\n");
    sb.append("Decorative Style:"+decorativeStyle);
    return sb.toString(); 

  } 

  @Override
  public int describeContents() {
    return 0;
  } 

  @Override
  public void writeToParcel(Parcel dest,int flags) {
    dest.writeInt(roomNum);
    dest.writeFloat(roomSpace);
    dest.writeBooleanArray(new boolean[]{hasAirConditioner,hasWifi});
    dest.writeString(decorativeStyle);
  } 

}

Room的声明为:

package com.android.service;
parcelable Room;

IRoom.aidl的代码为:

package com.android.service;
import com.android.service.Room; 

interface IRoom
{
 Room getRoom();
}

RoomService的代码为:

package com.android.service; 

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

public class RoomService extends Service{ 

  private IRoom.Stub mBinder=new IRoom.Stub() { 

    @Override
    public Room getRoom() throws RemoteException {
      Room room=new Room(3008,23.5f,true,true,"IKEA");
      return room;
    }
  }; 

  @Override
  public IBinder onBind(Intent intent) {
    return mBinder;
  } 

}

由于AndroidManifest.xml的代码不变,因而此处不再贴出。下面是客户端的代码:

package com.example.aidlsampleclient;
import com.android.service.IRoom;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.widget.Button;
import android.widget.Toast;
import android.view.View; 

public class MainActivity extends Activity implements View.OnClickListener{ 

  private static final String TAG="MainActivity";
  //private static final String SERVICE_ACTION="com.aidl.service.data";
  private static final String ROOM_SERVICE_ACTION="com.aidl.service.room"; 

  private Button bindServiceButton;
  private Button getServiceButton; 

  IRoom mRoom; 

  private ServiceConnection conn=new ServiceConnection()
  { 

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) { 

      Log.i(TAG,"----------------onServiceConnected--------");
      showLongToast("onServiceConnected");
      mRoom=IRoom.Stub.asInterface(service);
    } 

    @Override
    public void onServiceDisconnected(ComponentName name) { 

      Log.i(TAG,"----------------onServiceDisconnected-------------");
      mRoom=null; 

    } 

  }; 

  private void initView()
  {
    bindServiceButton=(Button)findViewById(R.id.bindServiceButton);
    getServiceButton=(Button)findViewById(R.id.getServiceButton);
    bindServiceButton.setOnClickListener(this);
    getServiceButton.setOnClickListener(this);
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  } 

  @Override
  public void onClick(View v) {
    switch(v.getId())
    {
    case R.id.bindServiceButton:
      bindService();
      break;
    case R.id.getServiceButton:
      getService();
       break;
    default:
       break;
    }
  } 

  private void bindService()
  {
    Intent intent=new Intent();
    intent.setAction(ROOM_SERVICE_ACTION);
    bindService(intent,conn,BIND_AUTO_CREATE);
  } 

  private void getService()
  {
    if(mRoom!=null)
    {
      try
      {
        showLongToast(mRoom.getRoom().toString());
      }
      catch (RemoteException e)
      {
        e.printStackTrace();
      }
    } 

  } 

  private void showLongToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
  } 

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    resent.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(conn);
  }
}

注意首先仍然是要将Room,IRoom的代码复制过去,否则会出错。

运行结果如下:

显然,客户端已经成功读取到服务信息。

注意,上面的所举的栗子其实不只是跨进程,还是跨应用。要注意的是,跨应用一定跨进程,但是跨进程不一定是跨应用。对于跨应用的情况,利用AIDL基本上是较好的解决了问题,但也只是“较好”而已,实际上并不完美,比如,如果要增加一个服务,如果利用AIDL的话,那么又要改写aidl文件,如果是涉及自定义对象,则还要增加自定义对象的声明,而且这种改变不只是Service端的改变,客户端也要跟着改变,显然这种解决方案不够优雅。

那么,有没有更优雅的方法呢?

当然有,那就是利用Service的onStartCommand(Intent intent, int flags, int startId)方法。

服务端代码如下:

package com.android.service; 

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast; 

public class RoomService extends Service{ 

  private static final String TAG="RoomService";
  private static final int CLEAN_SERVICE=0x1;
  private static final int ORDER_SERVICE=0x2;
  private static final int PACKAGE_SERVICE=0x3;
  private static final String SERVICE_KEY="ServiceName";
  @Override
  public void onStart(Intent intent, int startId) {
    showLog("onStart");
  } 

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    //String action=intent.getAction();
    Log.i(TAG,"onStartCommand"); 

    int actionFlag=intent.getIntExtra(SERVICE_KEY, -1);
   switch(actionFlag)
    {
    case CLEAN_SERVICE:
      showShortToast("Start Clean Service Right Now");
      break;
    case ORDER_SERVICE:
      showShortToast("Start Order Service Right Now");
      break;
    case PACKAGE_SERVICE:
      showShortToast("Start Package Service Right Now");
      break;
    default:
      break;
    }
    return super.onStartCommand(intent, flags, startId);
  } 

  private void showLog(String info)
  {
    Log.i(TAG,info);
  } 

  private void showShortToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();
  }
  @Override
  public void onDestroy() {
    showLog("onDestroy");
    super.onDestroy();
  } 

  @Override
  public void onCreate() {
    showLog("onCreate");
    super.onCreate();
  } 

  @Override
  public IBinder onBind(Intent intent) {
    showLog("onBind");
    return null;
  } 

  @Override
  public boolean onUnbind(Intent intent) {
    showLog("onUnbind");
    return super.onUnbind(intent);
  } 

}

客户端代码如下:

package com.example.aidlsampleclient;
import com.android.service.IRoom;
import com.android.service.RoomService; 

import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.widget.Button;
import android.widget.Toast;
import android.view.View; 

public class MainActivity extends Activity implements View.OnClickListener{ 

  private static final String TAG="MainActivity";
  private static final String ROOM_SERVICE_ACTION="com.aidl.service.room"; 

  private static final int CLEAN_SERVICE=0x1;
  private static final int ORDER_SERVICE=0x2;
  private static final int PACKAGE_SERVICE=0x3; 

  private static final String SERVICE_KEY="ServiceName"; 

  private Button cleanButton;
  private Button orderButton;
  private Button packageButton; 

  private void initView()
  {
    cleanButton=(Button)findViewById(R.id.cleanButton);
    orderButton=(Button)findViewById(R.id.orderButton);
    packageButton=(Button)findViewById(R.id.packageButton); 

    cleanButton.setOnClickListener(this);
    orderButton.setOnClickListener(this);
    packageButton.setOnClickListener(this);
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  } 

  @Override
  public void onClick(View v) {
  switch(v.getId())
    {
    case R.id.cleanButton:
      cleanAction();
      break;
    case R.id.orderButton:
      orderAction();
      break;
    case R.id.packageButton:
      packageAction();
      break;
    default:
       break;
    }
  } 

  private void cleanAction()
  {
    startAction(ROOM_SERVICE_ACTION,CLEAN_SERVICE);
  } 

  private void orderAction()
  {
    startAction(ROOM_SERVICE_ACTION,ORDER_SERVICE);
  } 

  private void packageAction()
  {
    startAction(ROOM_SERVICE_ACTION,PACKAGE_SERVICE);
  } 

  private void startAction(String actionName,int serviceFlag)
  {
    //Intent intent=new Intent(this,RoomService.class);
    Intent intent=new Intent();
    intent.setAction(actionName);
    intent.putExtra(SERVICE_KEY, serviceFlag);
    this.startService(intent);
  } 

  private void showLongToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
  } 

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
   resent.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
  }
}

运行结果如下:

显然,此时客户端顺利获取了服务。

上面举的是跨应用的例子,如果是在同一个应用的不同进程的话,则有更简单的实现方法。

RoomService的代码如下:

package com.android.service; 

import com.android.actions.Actions; 

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast; 

public class RoomService extends Service{ 

  private static final String TAG="RoomService";
  @Override
  public void onStart(Intent intent, int startId) {
    showLog("onStart");
  } 

  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    //String action=intent.getAction();
    Log.i(TAG,"onStartCommand");
    String action=intent.getAction();
    if(Actions.CLEAN_ACTION.equals(action))
    {
      showShortToast("Start Clean Service Right Now");
    }
    else if(Actions.ORDER_ACTION.equals(action))
    {
      showShortToast("Start Order Service Right Now");
    }
    else if(Actions.PACKAGE_ACTION.equals(action))
    {
      showShortToast("Start Package Service Right Now");
    }
    else
    {
      showShortToast("Wrong action");
    }
    return super.onStartCommand(intent, flags, startId);
  } 

  private void showLog(String info)
  {
    Log.i(TAG,info);
  } 

  private void showShortToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_SHORT).show();
  }
  @Override
  public void onDestroy() {
    showLog("onDestroy");
    super.onDestroy();
  } 

  @Override
  public void onCreate() { 

    showLog("onCreate");
    super.onCreate();
  } 

  @Override
  public IBinder onBind(Intent intent) {
    showLog("onBind");
    return null;
  } 

  @Override
  public boolean onUnbind(Intent intent) {
    showLog("onUnbind");
    return super.onUnbind(intent);
  } 

}

MainActivity的代码如下:

package com.android.activity;
import com.android.activity.R;
import com.android.service.RoomService; 

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.widget.Button;
import android.widget.Toast;
import android.view.View;
import com.android.actions.Actions; 

public class MainActivity extends Activity implements View.OnClickListener{ 

  private static final String TAG="MainActivity"; 

  private static final String SERVICE_KEY="ServiceName"; 

  private Button cleanButton;
  private Button orderButton;
  private Button packageButton; 

  private void initView()
  {
    cleanButton=(Button)findViewById(R.id.cleanButton);
    orderButton=(Button)findViewById(R.id.orderButton);
    packageButton=(Button)findViewById(R.id.packageButton); 

    cleanButton.setOnClickListener(this);
    orderButton.setOnClickListener(this);
    packageButton.setOnClickListener(this);
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
  } 

  @Override
  public void onClick(View v) {
   switch(v.getId())
    {
    case R.id.cleanButton:
      cleanAction();
      break;
    case R.id.orderButton:
      orderAction();
      break;
    case R.id.packageButton:
      packageAction();
      break;
    default:
       break;
    }
  } 

  private void cleanAction()
  {
    startAction(Actions.CLEAN_ACTION);
  } 

  private void orderAction()
  {
    startAction(Actions.ORDER_ACTION);
  } 

  private void packageAction()
  {
    startAction(Actions.PACKAGE_ACTION);
  } 

  private void startAction(String actionName)
  {
    Intent intent=new Intent(this,RoomService.class);
    intent.setAction(actionName);
    this.startService(intent);
  } 

  private void showLongToast(String info)
  {
    Toast.makeText(getBaseContext(), info, Toast.LENGTH_LONG).show();
  } 

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
   resent.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
  }
}

从打印的log可看出,客户端每调用一次Context.startService(Intent),Service就会重新执行一次onStartCommand---->onStart;但是使用AIDL的话,绑定服务之后,不会重复执行onStart,显然后者的代价更小。

Service:前台Service,像我们经常用的天气、音乐其实都利用了前台Service来实现

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android进程通信之Messenger和AIDL使用详解

    1. 前言 提到的进程间通信(IPC:Inter-Process Communication),在Android系统中,一个进程是不能直接访问另一个进程的内存的,需要提供一些机制在不同的进程之间进行通信,Android官方推出了AIDL(Android Interface Definition Language),它是基于Binder机制的. 上篇提到组件在与Service通信方法有三种. 实现IBinder Messenger AIDL 后面两种可以跨进程通信,是基于Binder机制的通信方式

  • Android编程实现AIDL(跨进程通信)的方法详解

    本文实例讲述了Android编程实现AIDL(跨进程通信)的方法.分享给大家供大家参考,具体如下: 一. 概述: 跨进程通信(AIDL),主要实现进程(应用)间数据共享功能. 二. 实现流程: 1. 服务器端实现: (1)目录结构,如下图: (2)实现*.aidl文件: A. IAIDLService.aidl实现: package com.focus.aidl; import com.focus.aidl.Person; interface IAIDLService { String getN

  • 实例讲解Android中的AIDL内部进程通信接口使用

    首先描述下我们想要实现的内容,我们希望在一个应用中通过点击按钮,去操作另一个进程中应用的音乐播放功能. 如图,我们点击"播放"时,系统就会去远程调用我们提供的一个service(与当前service不是同一个应用哦),然后操作service中的音乐播放,点击"停止"则会终止播放.想要重新播放的话,必须先点"销毁service",再点播放按钮哦.(至于这里为什么要先点销毁按钮才能播放,完全是为了给大家展示下,远程调用service时,怎么去解绑se

  • Android IPC机制利用Messenger实现跨进程通信

    写作原因:跨进程通信的实现和理解是Android进阶中重要的一环.下面博主分享IPC一些相关知识.操作及自己在学习IPC过程中的一些理解.这一章使用Messenger实现跨进程通信,其中bindService基础部分参见Android IPC机制绑定Service实现本地通信. 跨进程简介 在介绍使用Messenger跨进程通信之前先要了解以下问题:为什么需要跨进程通信?只有有了需求才有学习的价值.我个人将不同进程简单的理解为不同的应用程序(当然也有例外,比如可以在同一个应用程序中开启两个或多个

  • Android AIDL——进程通信机制详解

    Android  AIDL, Android进程机制通信机制,这里就整理下AIDL 的知识,帮助大家学习理解此部分知识! 什么是 AIDL AIDL 全称 Android Interface Definition Language,即 安卓接口描述语言.听起来很深奥,其实它的本质就是生成进程间通信接口的辅助工具.它的存在形式是一种 .aidl 文件,开发者需要做的就是在该文件中定义进程间通信的接口,编译的时候 IDE 就会根据我们的 .aidl 接口文件生成可供项目使用的 .java 文件,这和

  • 深入解读Android的内部进程通信接口AIDL

    意义: 由于每个应用进程都有自己的独立进程空间,在android平台上,一个进程通常不能访问另一个进程的内存空间,而我们经常需要夸进程传递对象,就需要把对象分解成操作对象可以理解的基本单元,并且有序的通过进程边界. 定义: AIDL(Android Interface Definition Language)是一种IDL语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码.如果在一个进程中(例如Activity

  • 详解Android 进程间通信的几种实现方式

    一.概述 由于应用程序之间不能共享内存.在不同应用程序之间交互数据(跨进程通讯),在Android SDK中提供了4种用于跨进程通讯的方式. 这4种方式正好对应于android系统中4种应用程序组件:Activity.Content Provider.Broadcast和Service.其中Activity可以跨进程调用其他应用程序的Activity:Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增.删.改操

  • 详解servlet调用的几种简单方式总结

    servlet调用的几种简单方式 这里总结的是我在学习web开发的过程中需要用到的几种比较常见的用于转发和调用servlet的方式,这些方式的使用率非常高.在网上总结了相关的方法,大多对于初学者不是特别的友好,自己总结了一下. 1.servlet直接转发到另一个servlet 我们在进行jsp页面点击按钮进行登录的时候,首先需要登录到进行登录检查的servlet,但是在下个jsp页面,我们需要那个页面通过servlet进行转发,所以需要从servlet直接跳转到另一个servlet,其实写法很简

  • 详解C++ 中的三种继承方式

    public 方式继承 基类成员对派生类的可见性对派生类来说,基类的公有成员和保护成员可见,基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态;基类的私有成员不可见,基类的私有成员仍然是私有的,派生类不可访问基类中的私有成员. 基类成员对派生类对象的可见性对派生类对象来说,基类的公有成员是可见的,其他成员是不可见的. 所以,在公有继承时,派生类的对象可以访问基类中的公有成员,派生类的成员函数可以访问基类中的公有成员和保护成员. 简单来说,派生类能访问基类的public, prote

  • 详解Java数组的四种拷贝方式

    目录 深拷贝与浅拷贝的区别 1.for循环进行拷贝 拷贝数值类型 拷贝引用类型 2.copyof/copyOfRange 拷贝数值类型 拷贝引用类型 3.arraycopy 拷贝数值类型 拷贝引用类型 4.clone 拷贝数值类型 拷贝引用类型 5.总结 深拷贝与浅拷贝的区别 假设现在有原数组A以及拷贝后的数组B,若是改变A中的某一个值,B数组随之相应的发生变化的拷贝方式称为浅拷贝,反之B数组不受影响,则称为深拷贝:简单总结一下两者的概念: 深拷贝:拷贝后,修改原数组,不会影响到新数组: 浅拷贝

  • 详解iOS 计步器的几种实现方式

    这篇文章介绍两种可以获取计步数据的方法,一种是采用CMPedometer获取手机计步器数据,另一种是采用HealthKit框架从手机健康App中获取计步数据.另外玩了一下写入数据到健康App.有描述不当之处,望指点. 花絮(用HealthKit框架构建app,写入数据到苹果健康app中,QQ和Keep等第三方app的运动数据都会随之改变,猜测它们的运动数据是直接从苹果健康app中获取,而且没有过滤掉其它数据来源.而微信运动的数据不会变,猜测其来源可能是使用CMPedometer类获取的,因为测试

  • 详解Java文件下载的几种实现方式

    Java文件下载的几种方式,具体如下: public HttpServletResponse download(String path, HttpServletResponse response) { try { // path是指欲下载的文件的路径. File file = new File(path); // 取得文件名. String filename = file.getName(); // 取得文件的后缀名. String ext = filename.substring(filena

  • 详解SpringBoot工程的三种搭建方式

    SpringBoot的主要目的是简化配置文件,通过少量配置即可运行Java程序,其强大的自动配置功能帮助开发者轻松实现配置装配,通过引入SpringBoot的 starter 就能实现想要的功能,不需要额外的配置. 目前SpringBoot工程有三种搭建方式: 通过Spring Initializr创建 通过IDEA创建工程 手动创建工程 官方生成工具 Spring团队提供一个非常方便的网页用于生成SpringBoot工程,打开浏览器进入Spring Initializr: 工程生成参数列表:

  • 详解Android 检测权限的三种写法

    本文介绍了详解Android 检测权限的三种写法,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 权限检测生效条件: targetSdkVersion 以及 compileSdkVersion 升级到 23 及以上 运行 Android 系统 6.0 及以上 三种检测权限写法: public static boolean checkPermission1(Context context, String[] permissions) { PackageManager p

  • 详解Android Activity中的几种监听器和实现方式

    Activity 在Activity中,使用findViewById(int resId)方法与布局中的控件绑定 View常用事件接口 View的事件监听是指用户与应用交互,当用户对View进行点击.长按.触摸.移动等动作时.程序对这些动作进行处理 OnClickListener    点击View时的监听 OnLongClickListener  长按View时的监听 OnTouchListener   触摸View时的监听 1.android系统中,OnClickListener 是一种处理

  • 详解Android GLide图片加载常用几种方法

    目录 缓存浅析 GLide图片加载方法 图片加载周期 图片格式(Bitmap,Gif) 缓存 集成网络框架 权限 占位符 淡入效果 变换 启动页/广告页 banner 固定宽高 圆角 圆形 总结 缓存浅析 为啥要做缓存? android默认给每个应用只分配16M的内存,所以如果加载过多的图片,为了 防止内存溢出 ,应该将图片缓存起来. 图片的三级缓存分别是: 1.内存缓存 2.本地缓存 3.网络缓存 其中,内存缓存应优先加载,它速度最快:本地缓存次优先加载,它速度也快:网络缓存不应该优先加载,它

随机推荐