目录:

一、Java程序的编译和运行

 1.单步操作

 PC:Hello.java 编译成 Hello.class,运行于 jvm。

javac Hello.java
java Hello

  Android:Hello.java 编译成 Hello.class,通过dx指令转换成.dex格式,运行于 dalvikvm。

javac Hello.java
dx --dex --output=Hello.jar Hello.class
dalvikvm -cp /mnt/android_fs/pack.jar Pack (启动方法1)
CLASSPATH=/mnt/android_fs/pack.jar app_process /mnt/android_fs Pack(启动方法2)

启动方式的差别:
dalvikvm
app_process :会创建2个binder线程: Binder_1, Binder_2 (实现读数据、解析数据、返回等操作)

2.Android编译系统(Android.mk)

把代码放到android源码中编译:
 添加Androd.mk,内容类似:  // 参考frameworks/base/cmds/am/Android.mk

include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_MODULE := pack
include $(BUILD_JAVA_LIBRARY)

3.使用java代码实现hello服务

 (1)IHelloService.aidl

 接口定义,编译生成IHelloService.java,里面有Stub  : onTransact, 它会分辨收到数据然后调用sayhello, sayhello_to;
  Proxy : 提供有sayhello, sayhello_to两个函数, 它们会构造数据然后发送给server。

/** {@hide} */
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
}

 (2)IHelloService.java

/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IHelloService.aidl
*/
/** {@hide} */
public interface IHelloService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements IHelloService
{
private static final java.lang.String DESCRIPTOR = "IHelloService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an IHelloService interface,
* generating a proxy if needed.
*/
public static IHelloService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof IHelloService))) {
return ((IHelloService)iin);
}
return new IHelloService.Stub.Proxy(obj);
} @Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_sayhello:
{
data.enforceInterface(DESCRIPTOR);
this.sayhello();
reply.writeNoException();
return true;
}
case TRANSACTION_sayhello_to:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _result = this.sayhello_to(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
} private static class Proxy implements IHelloService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void sayhello() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
} static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public void sayhello() throws android.os.RemoteException;
public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}

 (3)HelloService.java

  实现服务类: HelloService.java,在里面定义sayhello, sayhello_to;

import android.util.Slog;

/* 实现Hello服务的函数 */

public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
private int cnt1 = 0;
private int cnt2 = 0; public void sayhello() throws android.os.RemoteException {
cnt1++;
Slog.i(TAG, "sayhello : cnt = "+cnt1);
} public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
cnt2++;
Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
return cnt2;
}
}

 (4)IGoodbyeService.aidl (同HelloService)

/** {@hide} */
interface IGoodbyeService
{
void saygoodbye();
int saygoodbye_to(String name);
}

 (5)IGoodbyeService.java

/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IGoodbyeService.aidl
*/
/** {@hide} */
public interface IGoodbyeService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements IGoodbyeService
{
private static final java.lang.String DESCRIPTOR = "IGoodbyeService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an IGoodbyeService interface,
* generating a proxy if needed.
*/
public static IGoodbyeService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof IGoodbyeService))) {
return ((IGoodbyeService)iin);
}
return new IGoodbyeService.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_saygoodbye:
{
data.enforceInterface(DESCRIPTOR);
this.saygoodbye();
reply.writeNoException();
return true;
}
case TRANSACTION_saygoodbye_to:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _result = this.saygoodbye_to(_arg0);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements IGoodbyeService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public void saygoodbye() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_saygoodbye, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
@Override public int saygoodbye_to(java.lang.String name) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
mRemote.transact(Stub.TRANSACTION_saygoodbye_to, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_saygoodbye = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_saygoodbye_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public void saygoodbye() throws android.os.RemoteException;
public int saygoodbye_to(java.lang.String name) throws android.os.RemoteException;
}

 (6)GoodbyeService.java

import android.util.Slog;

/* 实现Goodbye服务的函数 */

public class GoodbyeService extends IGoodbyeService.Stub {
private static final String TAG = "GoodbyeService";
private int cnt1 = 0;
private int cnt2 = 0; public void saygoodbye() throws android.os.RemoteException {
cnt1++;
Slog.i(TAG, "saygoodbye : cnt = "+cnt1);
} public int saygoodbye_to(java.lang.String name) throws android.os.RemoteException {
cnt2++;
Slog.i(TAG, "saygoodbye_to "+name+" : cnt = "+cnt2);
return cnt2;
}
}

 (7)TestServer.java (addService, 循环)

import android.util.Slog;
import android.os.ServiceManager; /* 1. addService
* 2. while(true) { read data, parse data, call function, reply }
*/ public class TestServer {
private static final String TAG = "TestServer"; public static void main(String args[])
{
/* add Service */
Slog.i(TAG, "add hello service");
ServiceManager.addService("hello", new HelloService()); Slog.i(TAG, "add goodbye service");
ServiceManager.addService("goodbye", new GoodbyeService()); while (true)
{
try {
Thread.sleep(100);
} catch (Exception e){}
} }
}

 (8)TestClient.java (getService, 调用sayhello,sayhello_to(来自Proxy))

import android.util.Slog;
import android.os.ServiceManager;
import android.os.IBinder; /* 1. getService
* 2. 调用服务的sayhello,sayhello_to
*
*/ /* test_client <hello|goodbye> [name] */ public class TestClient {
private static final String TAG = "TestClient"; public static void main(String args[])
{
if (args.length == 0)
{
System.out.println("Usage: need parameter: <hello|goodbye> [name]");
return;
} if (args[0].equals("hello"))
{
/* 1. getService */
IBinder binder = ServiceManager.getService("hello");
if (binder == null)
{
System.out.println("can not get hello service");
Slog.i(TAG, "can not get hello service");
return;
} IHelloService svr = IHelloService.Stub.asInterface(binder); if (args.length == 1)
{
try {
svr.sayhello();
System.out.println("call sayhello");
Slog.i(TAG, "call sayhello");
} catch (Exception e) {}
}
else
{
try {
int cnt = svr.sayhello_to(args[1]);
System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);
Slog.i(TAG, "call sayhello_to "+args[1]+" : cnt = "+cnt);
} catch (Exception e) {
System.out.println("call sayhello_to , err :"+e);
Slog.i(TAG, "call sayhello_to , err : "+e);
}
}
}
else if (args[0].equals("goodbye"))
{
/* 1. getService */
IBinder binder = ServiceManager.getService("goodbye");
if (binder == null)
{
System.out.println("can not get goodbye service");
Slog.i(TAG, "can not get goodbye service");
return;
} IGoodbyeService svr = IGoodbyeService.Stub.asInterface(binder); if (args.length == 1)
{
try {
svr.saygoodbye();
System.out.println("call saygoodbye");
Slog.i(TAG, "call saygoodbye");
} catch (Exception e) {}
}
else
{
try {
int cnt = svr.saygoodbye_to(args[1]);
System.out.println("call saygoodbye_to "+args[1]+" : cnt = "+cnt);
Slog.i(TAG, "call saygoodbye_to "+args[1]+" : cnt = "+cnt);
} catch (Exception e) {}
}
}
}
}

 

 (9)Android.mk

# Copyright 2008 The Android Open Source Project
#
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS)
LOCAL_SRC_FILES := HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestServer.java
LOCAL_MODULE := TestServer
include $(BUILD_JAVA_LIBRARY) include $(CLEAR_VARS)
LOCAL_SRC_FILES := HelloService.java IHelloService.java GoodbyeService.java IGoodbyeService.java TestClient.java
LOCAL_MODULE := TestClient
include $(BUILD_JAVA_LIBRARY)

 编译&测试说明:

(1) AIDL
1. 把 IHelloService.aidl, IGoodbyeService.aidl 放入 frameworks/base/core/java/android/os
2. 修改 frameworks/base/Android.mk 添加一行
core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/IHelloService.aidl \
+ core/java/android/os/IGoodbyeService.aidl \ 3. mmm frameworks/base 4. 它会生成:
./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IHelloService.java
./out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os/IGoodbyeService.java (2) 编译:
把程序放到 /work/android-5.0.2/frameworks/testing/APP_0005_Binder_JAVA_App
执行: cd /work/android-5.0.2
. setenv
lunch // 选择单板 mmm frameworks/testing/APP_0005_Binder_JAVA_App
它会生成 TestServer.jar, TestClient.jar 复制文件到NFS目录
cp /work/android-5.0.2/out/target/product/tiny4412/system/framework/Test*.jar /work/nfs_root/android_fs/

(3) 测试:

logcat TestServer:* TestClient:* HelloService:* *:S &
CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer &
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello 100ask.taobao.com
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient goodbye weidongshan

、内部机制

1.Client端
1.1 ServiceManagerProxy中mRemote的构造 (用于addService/getService)
   使用0直接构造出一个java BinderProxy对象
getIServiceManager().addService  / getIServiceManager().getService

getIServiceManager()
        return ServiceManagerNative.asInterface(BinderInternal.getContextObject())

a. BinderInternal.getContextObject()  // 得到了一个Java BinderProxy对象, 其中mObject指向new BpBinder(0);
   它是一个JNI调用,对应 android_os_BinderInternal_getContextObject // android_util_Binder.cpp
   
   android_os_BinderInternal_getContextObject
           sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
                                                                                               getStrongProxyForHandle(0);
                                                                                                       b = new BpBinder(handle);  // mHandle = 0
            return javaObjectForIBinder(env, b);        // b = new BpBinder(0), mHandle = 0
            
                                    // 使用c代码调用NewObject来创建JAVA BinderProxy对象
                                    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
                                    
                                    // 设置该对象的mObject = val.get = b = new BpBinder(0)
                                    env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
                                    
                                    return object;

b. ServiceManagerNative.asInterface
            new ServiceManagerProxy(obj); // obj = BinderProxy对象
                            mRemote = obj = BinderProxy对象, 其中mObject指向new BpBinder(0);

1.2 hello服务里的mRemote如何构造
a. IBinder binder = ServiceManager.getService("hello");
 它的返回值就是一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)
new ServiceManagerProxy().getService("hello")
            ....
            IBinder binder = reply.readStrongBinder();
                                                                nativeReadStrongBinder  // Parcel.java

nativeReadStrongBinder是一个JNI调用, 对应的代码是 android_os_Parcel_readStrongBinder                                                                
android_os_Parcel_readStrongBinder    
      // 把java Parce对象转换为c++ Parcel对象
      // client程序向sevice_manager发出getService请求,
      // 得到一个回复reply, 它里面含有flat_binder_object
      // 它被封装成一个c++ Parcel对象
        Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
        
        /* parcel->readStrongBinder()应该是一个 new BpBinder(handle)
         *             unflatten_binder(ProcessState::self(), *this, &val);
         *                  *out = proc->getStrongProxyForHandle(flat->handle);
         *                                  b = new BpBinder(handle);
         */
        
      // 它会创建一个java BinderProxy对象, 其中的mObject=new BpBinder(handle)对象
        return javaObjectForIBinder(env, parcel->readStrongBinder());

b. IHelloService svr = IHelloService.Stub.asInterface(binder);
                                                        new IHelloService.Stub.Proxy(obj);  // obj = 步骤a得到的binder
                                                                        mRemote = remote;

1.3 现在知道了:mRemote就是一个java BinderProxy 对象
    看一下mRemote.transact()
                                    transactNative(code, data, reply, flags);
                                    它是一个JNI调用,对应android_os_BinderProxy_transact

android_os_BinderProxy_transact
   // 从java BinderProxy对象中把mObject取出, 它就是一个BpBinder对象
    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);                                    
    
    // 然后调用BpBinder的transact
    status_t err = target->transact(code, *data, reply, flags);

2.Server端

2.1 server如何读取数据
 使用app_process来启动server进程,

/*测试指令*/
logcat TestServer:* TestClient:* HelloService:* *:S &
CLASSPATH=/mnt/android_fs/TestServer.jar app_process / TestServer &
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello
CLASSPATH=/mnt/android_fs/TestClient.jar app_process / TestClient hello sheldon /*参考源码*/
// app_process: frameworks\base\cmds\app_process\app_main.cpp

它会先创建子线程(前面示例提到的两个binder线程:Binder_1, Binder_2):
AppRuntime::onStarted()
        proc->startThreadPool();
                        spawnPooledThread(true);
                                sp<Thread> t = new PoolThread(isMain);
                                t->run(name.string());
                                        // 它会创建子线程, 并执行threadLoop
                                           IPCThreadState::self()->joinThreadPool(mIsMain);
                                           {
                                                    do {
                                                                    result = getAndExecuteCommand();
                                                                                            result = talkWithDriver();
                                                                                            result = executeCommand(cmd);
                                                                                                                    对于BR_TRANSACTION数据,
                                                                                                                    sp<BBinder> b((BBinder*)tr.cookie); //将.cookie转换成BBinder对象
                                                                                                                    error = b->transact(tr.code, buffer, &reply, tr.flags); //并调用其transact方法
                                                 } while(...)
                                           }

2.2 server读到数据后怎么调用服务PRC层的onTransact函数
  在addService时设置.ptr/.cookie
  ServiceManager.addService("hello", new HelloService());

结论:
① addService会通过JNI调用c++函数:
        创建一个BBinder派生类JavaBBinder对象,
            它的.mObject指向JAVA对象: new HelloService()
            它含有onTransact函数
        把这个对象存入.cookie(最终存入binder驱动中该服务对应的binder_node.cookie)

② server进程从驱动中读到数据,里面含有.cookie
    把它转换为BBinder对象,
    调用它的transact函数
    最终调用到派生类JavaBBinder中定义的onTransact函数

③ JavaBBinder中定义的onTransact函数(c++)
    它通过JNI调用java Binder的execTransact方法,
    然后调用Binder派生类IHelloService.Stub中定义的onTransact函数(JAVA)

④ IHelloService.Stub中定义的onTransact函数(JAVA):
        分析数据
        调用sayhello/sayhello_to

源码阅读
(1) ServiceManager.addService("hello", new HelloService());
    ServiceManagerProxy.addService:
            // Parcel.java
            data.writeStrongBinder(service);
                            nativeWriteStrongBinder(mNativePtr, val); // val = service = new HelloService()
                            它是一个JNI调用,对应android_os_Parcel_writeStrongBinder(c++)

(2) android_os_Parcel_writeStrongBinder(c++)
    它会构造一个JavaBBinder对象(c++),.mObject=new HelloService() JAVA对象
    然后让.cookie=JavaBBinder对象(c++)
    
    // 把Java Parcel转换为c++ Parcel
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    
    // .cookie = ibinderForJavaObject(env, object)得到一个JavaBBinder对象
    parcel->writeStrongBinder(ibinderForJavaObject(env, object))

(3) ibinderForJavaObject(env, object) //object = new HelloService()
    把一个Java对象(new HelloService())转换为c++ IBinder对象
    
    JavaBBinderHolder* jbh = (JavaBBinderHolder*)env->GetLongField(obj, gBinderOffsets.mObject);
    return jbh != NULL ? jbh->get(env, obj) : NULL;
                                                     b = new JavaBBinder(env, obj); // obj = new HelloService()
                                                                 mObject = new HelloService()

(4) 从驱动中得过了.cookie, 它是一个JavaBBinder对象
    调用它的transact函数,导致JavaBBinder对象的onTransact被调用
    
    JavaBBinder::onTransact (调用java里的某个函数)
    
            // mObject指向 HelloService对象
            // gBinderOffsets.mExecTransact指向: java Binder类中的execTransact方法
            // 调用HelloService(派生自Binder)对象中的execTransact方法
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);

(5) java Binder execTransact:  
                res = onTransact(code, data, reply, flags);
                                    调用HelloService中的onTransact方法(来自IHelloService.Stube)
                                        分辨数据
                                        调用sayhello/sayhello_to

-end-

Android : 跟我学Binder --- (6) JAVA实现的更多相关文章

  1. Android : 跟我学Binder --- (5) C++实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  2. Android : 跟我学Binder --- (4) 驱动情景分析

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  3. Android : 跟我学Binder --- (3) C程序示例

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  4. Android : 跟我学Binder --- (2) AIDL分析及手动实现

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  5. Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?

    目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...

  6. Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务

    有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...

  7. 写给 Android 应用工程师的 Binder 原理剖析

    写给 Android 应用工程师的 Binder 原理剖析 一. 前言 这篇文章我酝酿了很久,参考了很多资料,读了很多源码,却依旧不敢下笔.生怕自己理解上还有偏差,对大家造成误解,贻笑大方.又怕自己理 ...

  8. 【Android】进程间通信IPC——Binder

    Binder是Android中的跨进程通信方式,bindService的时候,服务端返回Binder对象,通过该对象客户端可以从服务端获取数据.在进程间通信IPC——AIDL中创建了ICustomAi ...

  9. 【Android - IPC】之Binder机制简介

    参考资料: 1.<Android开发艺术探索>第二章2.3.3 Binder 2.[Android Binder设计与实现-设计篇] 3.[Android Binder机制介绍] 1. 什 ...

随机推荐

  1. dubbo框架整合常见问题

    逆向工程常见问题总结 tomcat7插件启动项目卡在:log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for ...

  2. usdt节点启动慢和队列深度超出了范围问题

    usdt节点启动慢和队列深度超出了范围问题 usdt的连接节点报错Work queue depth exceeded(队列深度超出了范围)大概是什么问题?重启了几次节点都不行队列深度超出了范围,估计是 ...

  3. 石家庄铁道大学课程信息管理系统(javaWeb+servlet+Mysql)

    实现网页版的课程管理系统,具有增删改查的功能. 1.首先连接数据库,具体数据库的使用及如何连接eclipse,参考     https://blog.csdn.net/lrici/article/de ...

  4. vs2017添加引用出错:对COM组件的调用返回了错误HRESULT E_FAIL

    1.以管理员身份打开 Developer Command Prompt for VS 2017(vs2017开发人员命令提示符) 2.定位到你的vs2017的安装目录 例:E:\Program Fil ...

  5. zabbix 乱码问题

    一.乱码原因 查看cpu负载,中文乱码如下 这个问题是由于zabbix的web端没有中文字库,我们最需要把中文字库加上即可 二.解决zabbix乱码方法 2.1 上传字体文件到zabbix中 找到本地 ...

  6. nodejs cannot find module 'mysql' 问题分析

    在windows平台下,测试nodejs连接mysql数据库. 首先 在控制台中安装mysql依赖包 npm install mysql 安装成功后,mysql依赖包可以在User目录中的node_m ...

  7. 【BCFTOOLS】按样本拆分VCF文件

    在对vcf的操作有这样三个软件: Vcftools:主要用于群体分析,文本处理的功能不是很强大,虽然这个软件也可以拆分样本,但是这种拆分不涉及文件的处理,只是保留在分析流程里. GATK .x:这个软 ...

  8. latch release ......

    MainControl_cfg.c brings error:  not defined. /* e_TIMER_MCtrlLatchReleaseTime  */     TIMER_ID_MCtr ...

  9. What's the Python Launcher?

    Look! Python launcher 你可能在他处见到过这鬼东西,when you install or uninstall python, and so on.那么你肯定与我一样对这个鬼东西起 ...

  10. Docker Swarm 负载均衡详解 or 模式选择

    Docker Swarm 负载均衡详解 Swarm模式内置DNS组件,可以自动为集群中的每个服务分配DNS记录. Swarm manager使用内部负载均衡,根据服务的DNS名称在集群内的服务之间分发 ...