这个Server继承了Android系统应用程序框架层提供的Service类,当它被启动时,运行在一个独立的进程中。当这个Server被启动时,它的onCreate函数就会被调用,然后它就通过ServiceManager的addService接口来添加MemoryService了:
[java] view plain copy print ?
- memoryService = new MemoryService();
-
- try {
- ServiceManager.addService("AnonymousSharedMemory", memoryService);
- Log.i(LOG_TAG, "Succeed to add memory service.");
- } catch (RuntimeException ex) {
- Log.i(LOG_TAG, "Failed to add Memory Service.");
- ex.printStackTrace();
- }
[java] view plain copy print ?
- memoryService = new MemoryService();
-
- try {
- ServiceManager.addService("AnonymousSharedMemory", memoryService);
- Log.i(LOG_TAG, "Succeed to add memory service.");
- } catch (RuntimeException ex) {
- Log.i(LOG_TAG, "Failed to add Memory Service.");
- ex.printStackTrace();
- }
memoryService = new MemoryService();
try {
ServiceManager.addService("AnonymousSharedMemory", memoryService);
Log.i(LOG_TAG, "Succeed to add memory service.");
} catch (RuntimeException ex) {
Log.i(LOG_TAG, "Failed to add Memory Service.");
ex.printStackTrace();
}
这样,当这个Server成功启动了,Client就可以通过ServiceManager的getService接口来获取这个MemoryService了。
接着,我们就来看Client端的实现。Client端是一个Activity,实现在src/shy/luo/ashmem/Client.java文件中:
[java] view plain copy print ?
- package shy.luo.ashmem;
-
- import java.io.FileDescriptor;
- import java.io.IOException;
-
- import shy.luo.ashmem.R;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.MemoryFile;
- import android.os.ParcelFileDescriptor;
- import android.os.ServiceManager;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
-
- public class Client extends Activity implements OnClickListener {
- private final static String LOG_TAG = "shy.luo.ashmem.Client";
-
- IMemoryService memoryService = null;
- MemoryFile memoryFile = null;
-
- private EditText valueText = null;
- private Button readButton = null;
- private Button writeButton = null;
- private Button clearButton = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- IMemoryService ms = getMemoryService();
- if(ms == null) {
- startService(new Intent("shy.luo.ashmem.server"));
- } else {
- Log.i(LOG_TAG, "Memory Service has started.");
- }
-
- valueText = (EditText)findViewById(R.id.edit_value);
- readButton = (Button)findViewById(R.id.button_read);
- writeButton = (Button)findViewById(R.id.button_write);
- clearButton = (Button)findViewById(R.id.button_clear);
-
- readButton.setOnClickListener(this);
- writeButton.setOnClickListener(this);
- clearButton.setOnClickListener(this);
-
- Log.i(LOG_TAG, "Client Activity Created.");
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- Log.i(LOG_TAG, "Client Activity Resumed.");
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- Log.i(LOG_TAG, "Client Activity Paused.");
- }
-
- @Override
- public void onClick(View v) {
- if(v.equals(readButton)) {
- int val = 0;
-
- MemoryFile mf = getMemoryFile();
- if(mf != null) {
- try {
- byte[] buffer = new byte[4];
- mf.readBytes(buffer, 0, 0, 4);
-
- val = (buffer[0] << 24) | ((buffer[1] & 0xFF) << 16) | ((buffer[2] & 0xFF) << 8) | (buffer[3] & 0xFF);
- } catch(IOException ex) {
- Log.i(LOG_TAG, "Failed to read bytes from memory file.");
- ex.printStackTrace();
- }
- }
-
- String text = String.valueOf(val);
- valueText.setText(text);
- } else if(v.equals(writeButton)) {
- String text = valueText.getText().toString();
- int val = Integer.parseInt(text);
-
- IMemoryService ms = getMemoryService();
- if(ms != null) {
- try {
- ms.setValue(val);
- } catch(RemoteException ex) {
- Log.i(LOG_TAG, "Failed to set value to memory service.");
- ex.printStackTrace();
- }
- }
- } else if(v.equals(clearButton)) {
- String text = "";
- valueText.setText(text);
- }
- }
-
- private IMemoryService getMemoryService() {
- if(memoryService != null) {
- return memoryService;
- }
-
- memoryService = IMemoryService.Stub.asInterface(
- ServiceManager.getService("AnonymousSharedMemory"));
-
- Log.i(LOG_TAG, memoryService != null ? "Succeed to get memeory service." : "Failed to get memory service.");
-
- return memoryService;
- }
-
- private MemoryFile getMemoryFile() {
- if(memoryFile != null) {
- return memoryFile;
- }
-
- IMemoryService ms = getMemoryService();
- if(ms != null) {
- try {
- ParcelFileDescriptor pfd = ms.getFileDescriptor();
- if(pfd == null) {
- Log.i(LOG_TAG, "Failed to get memory file descriptor.");
- return null;
- }
-
- try {
- FileDescriptor fd = pfd.getFileDescriptor();
- if(fd == null) {
- Log.i(LOG_TAG, "Failed to get memeory file descriptor.");
- return null;
- }
-
- memoryFile = new MemoryFile(fd, 4, "r");
- } catch(IOException ex) {
- Log.i(LOG_TAG, "Failed to create memory file.");
- ex.printStackTrace();
- }
- } catch(RemoteException ex) {
- Log.i(LOG_TAG, "Failed to get file descriptor from memory service.");
- ex.printStackTrace();
- }
- }
-
- return memoryFile;
- }
- }
[java] view plain copy print ?
- package shy.luo.ashmem;
-
- import java.io.FileDescriptor;
- import java.io.IOException;
-
- import shy.luo.ashmem.R;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.os.MemoryFile;
- import android.os.ParcelFileDescriptor;
- import android.os.ServiceManager;
- import android.os.RemoteException;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
-
- public class Client extends Activity implements OnClickListener {
- private final static String LOG_TAG = "shy.luo.ashmem.Client";
-
- IMemoryService memoryService = null;
- MemoryFile memoryFile = null;
-
- private EditText valueText = null;
- private Button readButton = null;
- private Button writeButton = null;
- private Button clearButton = null;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- IMemoryService ms = getMemoryService();
- if(ms == null) {
- startService(new Intent("shy.luo.ashmem.server"));
- } else {
- Log.i(LOG_TAG, "Memory Service has started.");
- }
-
- valueText = (EditText)findViewById(R.id.edit_value);
- readButton = (Button)findViewById(R.id.button_read);
- writeButton = (Button)findViewById(R.id.button_write);
- clearButton = (Button)findViewById(R.id.button_clear);
-
- readButton.setOnClickListener(this);
- writeButton.setOnClickListener(this);
- clearButton.setOnClickListener(this);
-
- Log.i(LOG_TAG, "Client Activity Created.");
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- Log.i(LOG_TAG, "Client Activity Resumed.");
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- Log.i(LOG_TAG, "Client Activity Paused.");
- }
-
- @Override
- public void onClick(View v) {
- if(v.equals(readButton)) {
- int val = 0;
-
- MemoryFile mf = getMemoryFile();
- if(mf != null) {
- try {
- byte[] buffer = new byte[4];
- mf.readBytes(buffer, 0, 0, 4);
-
- val = (buffer[0] << 24) | ((buffer[1] & 0xFF) << 16) | ((buffer[2] & 0xFF) << 8) | (buffer[3] & 0xFF);
- } catch(IOException ex) {
- Log.i(LOG_TAG, "Failed to read bytes from memory file.");
- ex.printStackTrace();
- }
- }
-
- String text = String.valueOf(val);
- valueText.setText(text);
- } else if(v.equals(writeButton)) {
- String text = valueText.getText().toString();
- int val = Integer.parseInt(text);
-
- IMemoryService ms = getMemoryService();
- if(ms != null) {
- try {
- ms.setValue(val);
- } catch(RemoteException ex) {
- Log.i(LOG_TAG, "Failed to set value to memory service.");
- ex.printStackTrace();
- }
- }
- } else if(v.equals(clearButton)) {
- String text = "";
- valueText.setText(text);
- }
- }
-
- private IMemoryService getMemoryService() {
- if(memoryService != null) {
- return memoryService;
- }
-
- memoryService = IMemoryService.Stub.asInterface(
- ServiceManager.getService("AnonymousSharedMemory"));
-
- Log.i(LOG_TAG, memoryService != null ? "Succeed to get memeory service." : "Failed to get memory service.");
-
- return memoryService;
- }
-
- private MemoryFile getMemoryFile() {
- if(memoryFile != null) {
- return memoryFile;
- }
-
- IMemoryService ms = getMemoryService();
- if(ms != null) {
- try {
- ParcelFileDescriptor pfd = ms.getFileDescriptor();
- if(pfd == null) {
- Log.i(LOG_TAG, "Failed to get memory file descriptor.");
- return null;
- }
-
- try {
- FileDescriptor fd = pfd.getFileDescriptor();
- if(fd == null) {
- Log.i(LOG_TAG, "Failed to get memeory file descriptor.");
- return null;
- }
-
- memoryFile = new MemoryFile(fd, 4, "r");
- } catch(IOException ex) {
- Log.i(LOG_TAG, "Failed to create memory file.");
- ex.printStackTrace();
- }
- } catch(RemoteException ex) {
- Log.i(LOG_TAG, "Failed to get file descriptor from memory service.");
- ex.printStackTrace();
- }
- }
-
- return memoryFile;
- }
- }
package shy.luo.ashmem;
import java.io.FileDescriptor;
import java.io.IOException;
import shy.luo.ashmem.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.MemoryFile;
import android.os.ParcelFileDescriptor;
import android.os.ServiceManager;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class Client extends Activity implements OnClickListener {
private final static String LOG_TAG = "shy.luo.ashmem.Client";
IMemoryService memoryService = null;
MemoryFile memoryFile = null;
private EditText valueText = null;
private Button readButton = null;
private Button writeButton = null;
private Button clearButton = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
IMemoryService ms = getMemoryService();
if(ms == null) {
startService(new Intent("shy.luo.ashmem.server"));
} else {
Log.i(LOG_TAG, "Memory Service has started.");
}
valueText = (EditText)findViewById(R.id.edit_value);
readButton = (Button)findViewById(R.id.button_read);
writeButton = (Button)findViewById(R.id.button_write);
clearButton = (Button)findViewById(R.id.button_clear);
readButton.setOnClickListener(this);
writeButton.setOnClickListener(this);
clearButton.setOnClickListener(this);
Log.i(LOG_TAG, "Client Activity Created.");
}
@Override
public void onResume() {
super.onResume();
Log.i(LOG_TAG, "Client Activity Resumed.");
}
@Override
public void onPause() {
super.onPause();
Log.i(LOG_TAG, "Client Activity Paused.");
}
@Override
public void onClick(View v) {
if(v.equals(readButton)) {
int val = 0;
MemoryFile mf = getMemoryFile();
if(mf != null) {
try {
byte[] buffer = new byte[4];
mf.readBytes(buffer, 0, 0, 4);
val = (buffer[0] << 24) | ((buffer[1] & 0xFF) << 16) | ((buffer[2] & 0xFF) << 8) | (buffer[3] & 0xFF);
} catch(IOException ex) {
Log.i(LOG_TAG, "Failed to read bytes from memory file.");
ex.printStackTrace();
}
}
String text = String.valueOf(val);
valueText.setText(text);
} else if(v.equals(writeButton)) {
String text = valueText.getText().toString();
int val = Integer.parseInt(text);
IMemoryService ms = getMemoryService();
if(ms != null) {
try {
ms.setValue(val);
} catch(RemoteException ex) {
Log.i(LOG_TAG, "Failed to set value to memory service.");
ex.printStackTrace();
}
}
} else if(v.equals(clearButton)) {
String text = "";
valueText.setText(text);
}
}
private IMemoryService getMemoryService() {
if(memoryService != null) {
return memoryService;
}
memoryService = IMemoryService.Stub.asInterface(
ServiceManager.getService("AnonymousSharedMemory"));
Log.i(LOG_TAG, memoryService != null ? "Succeed to get memeory service." : "Failed to get memory service.");
return memoryService;
}
private MemoryFile getMemoryFile() {
if(memoryFile != null) {
return memoryFile;
}
IMemoryService ms = getMemoryService();
if(ms != null) {
try {
ParcelFileDescriptor pfd = ms.getFileDescriptor();
if(pfd == null) {
Log.i(LOG_TAG, "Failed to get memory file descriptor.");
return null;
}
try {
FileDescriptor fd = pfd.getFileDescriptor();
if(fd == null) {
Log.i(LOG_TAG, "Failed to get memeory file descriptor.");
return null;
}
memoryFile = new MemoryFile(fd, 4, "r");
} catch(IOException ex) {
Log.i(LOG_TAG, "Failed to create memory file.");
ex.printStackTrace();
}
} catch(RemoteException ex) {
Log.i(LOG_TAG, "Failed to get file descriptor from memory service.");
ex.printStackTrace();
}
}
return memoryFile;
}
}
Client端的界面主要包含了三个按钮Read、Write和Clear,以及一个用于显示内容的文本框。
这个Activity在onCreate时,会通过startService接口来启动我们前面定义的Server进程。调用startService时,需要指定要启动的服务的名称,这里就是"shy.luo.ashmem.server"了,后面我们会在程序的描述文件AndroidManifest.xml看到前面的Server类是如何和名称"shy.luo.ashmem.server"关联起来的。关于调用startService函数来启动自定义服务的过程,可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析一文。
内部函数getMemoryService用来获取IMemoryService。如果是第一次调用该函数,则会通过ServiceManager的getService接口来获得这个IMemoryService接口,然后保存在类成员变量memoryService中,以后再调用这个函数时,就可以直接返回memoryService了。
内部函数getMemoryFile用来从MemoryService中获得匿名共享内存文件的描述符。同样,如果是第一次调用该函数,则会通过IMemoryService的getFileDescriptor接口来获得MemoryService中的匿名共享内存文件的描述符,然后用这个文件描述符来创建一个MemoryFile实例,并保存在类成员变量memoryFile中,以后再调用这个函数时,就可以直接返回memoryFile了。
有了memoryService和memoryFile后,我们就可以在Client端访问Server端创建的匿名共享内存了。点击Read按钮时,就通过memoryFile的readBytes接口把共享内存中的整数读出来,并显示在文本框中;点击Write按钮时,就通过memoryService这个代理类的setVal接口来调用MemoryService的本地实现类的setVal服务,从而把文本框中的数值写到Server端创建的匿名共享内存中去;点击Clear按钮时,就会清空文本框的内容。这样,我们就可以通过Read和Write按钮来验证我们是否在Client和Server两个进程中实现内存共享了。
现在,我们再来看看Client界面的配置文件,它定义在res/layout/main.xml文件中:
[html] view plain copy print ?
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- >
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/value">
- </TextView>
- <EditText
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:id="@+id/edit_value"
- android:hint="@string/hint">
- </EditText>
- </LinearLayout>
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:gravity="center">
- <Button
- android:id="@+id/button_read"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/read">
- </Button>
- <Button
- android:id="@+id/button_write"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/write">
- </Button>
- <Button
- android:id="@+id/button_clear"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/clear">
- </Button>
- </LinearLayout>
- </LinearLayout>