• IPC 调用示例


    这几天看了高焕堂关于

    高焕堂——Android框架底层结构知多少?

    http://www.android1.net/Topic.aspx?BoardID=11&TopicID=703

    看看人家写的东西和大陆这边的文章还是有一些差距。拿了高先生的代码自己编译了一下,有所收获。特将代码贴出。

    Android中一个app就是一个process,那么跨process如何通讯呢?答案是IPC,但是自己在模拟器上测试了了一下,

    感觉速度还是挺慢的。以下几点应该注意以下:

    1. 注册remote process,在androidmenifest.xml中测试远程服务:

    	<service android:name="com.fp.app.service.FPService" android:process=":remote">
    			<intent-filter>
    				<action android:name="com.fp.app.service.FPService" />
    			</intent-filter>
           </service>
    

    其中

    <action android:name="com.fp.app.service.FPService" /> 为client段调用的名称,你可以定义多个remote process,只要保证 intent filter中名称不一样即可。
    2. 如果启动了多个remote process,在启动另外之前,应该将前面的process ubind.
    super.unbindService(mConnection);
    否则,会抛出如下错误:
    I/ActivityManager(  583): Stopping service: com.fp.app.readbinder/com.fp.app.service.myService
    E/ActivityThread(  868): Activity com.fp.app.readbinder.IPCSyncActivity has leaked ServiceConnection com.fp.app.readbinder.IPCSyncActivity$2@4373599
    E/ActivityThread(  868): android.app.ServiceConnectionLeaked: Activity com.fp.app.readbinder.IPCSyncActivity has leaked ServiceConnection com.fp.app
    E/ActivityThread(  868):        at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:886)
    E/ActivityThread(  868):        at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:781)
    E/ActivityThread(  868):        at android.app.ApplicationContext.bindService(ApplicationContext.java:820)
    E/ActivityThread(  868):        at android.content.ContextWrapper.bindService(ContextWrapper.java:307)
    E/ActivityThread(  868):        at com.fp.app.readbinder.IPCSyncActivity.bindService(IPCSyncActivity.java:48)
    E/ActivityThread(  868):        at com.fp.app.readbinder.IPCSyncActivity.onCreate(IPCSyncActivity.java:41)
    E/ActivityThread(  868):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
    E/ActivityThread(  868):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231)
    E/ActivityThread(  868):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284)
    E/ActivityThread(  868):        at android.app.ActivityThread.access$1800(ActivityThread.java:112)
    E/ActivityThread(  868):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
    E/ActivityThread(  868):        at android.os.Handler.dispatchMessage(Handler.java:99)
    E/ActivityThread(  868):        at android.os.Looper.loop(Looper.java:123)
    E/ActivityThread(  868):        at android.app.ActivityThread.main(ActivityThread.java:3948)
    E/ActivityThread(  868):        at java.lang.reflect.Method.invokeNative(Native Method)
    E/ActivityThread(  868):        at java.lang.reflect.Method.invoke(Method.java:521)
    E/ActivityThread(  868):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
    E/ActivityThread(  868):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
    E/ActivityThread(  868):        at dalvik.system.NativeStart.main(Native Method)
    W/ActivityManager(  583): Unbind failed: could not find connection for android.os.BinderProxy@436f90f0
    E/ActivityThread(  868): Activity com.fp.app.readbinder.IPCSyncActivity has leaked ServiceConnection com.fp.app.readbinder.IPCSyncActivity$1@4373598
    E/ActivityThread(  868): android.app.ServiceConnectionLeaked: Activity com.fp.app.readbinder.IPCSyncActivity has leaked ServiceConnection com.fp.app
    E/ActivityThread(  868):        at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:886)
    E/ActivityThread(  868):        at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:781)
    E/ActivityThread(  868):        at android.app.ApplicationContext.bindService(ApplicationContext.java:820)
    E/ActivityThread(  868):        at android.content.ContextWrapper.bindService(ContextWrapper.java:307)
    E/ActivityThread(  868):        at com.fp.app.readbinder.IPCSyncActivity.bindService(IPCSyncActivity.java:46)
    E/ActivityThread(  868):        at com.fp.app.readbinder.IPCSyncActivity.onCreate(IPCSyncActivity.java:41)
    E/ActivityThread(  868):        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1123)
    E/ActivityThread(  868):        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2231)
    E/ActivityThread(  868):        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2284)
    E/ActivityThread(  868):        at android.app.ActivityThread.access$1800(ActivityThread.java:112)
    E/ActivityThread(  868):        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
    E/ActivityThread(  868):        at android.os.Handler.dispatchMessage(Handler.java:99)
    E/ActivityThread(  868):        at android.os.Looper.loop(Looper.java:123)
    E/ActivityThread(  868):        at android.app.ActivityThread.main(ActivityThread.java:3948)
    E/ActivityThread(  868):        at java.lang.reflect.Method.invokeNative(Native Method)
    E/ActivityThread(  868):        at java.lang.reflect.Method.invoke(Method.java:521)
    E/ActivityThread(  868):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
    E/ActivityThread(  868):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
    E/ActivityThread(  868):        at dalvik.system.NativeStart.main(Native Method)
    W/ActivityManager(  583): Unbind failed: could not find connection for android.os.BinderProxy@436f6ba8
    
    3. 是否process启动,可以通过ddms观察状态,画红线部分为新的remote process.一般一个process会启动3个或者3个以下thread 进行ipc通讯.

    废话少说,可以通过下面的代码进行体会:
    package com.fp.app.debug;
    
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.io.Writer;
    
    import android.util.Log;
    
    public class DebugLog {
    	public final static boolean DEBUG = false;
    
    	public static void log(String message) {
    		if (true) {
    			String fullClassName = Thread.currentThread().getStackTrace()[3].getClassName();
    			String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1);
    			String methodName = Thread.currentThread().getStackTrace()[3].getMethodName();
    			int lineNumber = Thread.currentThread().getStackTrace()[3].getLineNumber();
    
    			Log.d(className + "." + methodName + "():" + lineNumber, message);
    		}
    	}
    	
    	
    	public static void printThreadId(String message) {
    		if (DEBUG) {
    			Log.d(message, String.valueOf(Thread.currentThread().getId()));
    		}
    	}
    
    	public static void log(String tag, String message) {
    		if (DEBUG) {
    			String methodName = Thread.currentThread().getStackTrace()[3].getMethodName();
    			int lineNumber = Thread.currentThread().getStackTrace()[3].getLineNumber();
    
    			Log.d(tag + "." + methodName + "():" + lineNumber, message);
    		}
    	}
    
    	public static void printTrace(String message) {
    		if (DEBUG) {
    			printIllegalArgumentException("", message);
    		}
    	}
    
    	public static String getStackTrace(Throwable throwable) {
    		Writer writer = new StringWriter();
    		PrintWriter printWriter = new PrintWriter(writer);
    		throwable.printStackTrace(printWriter);
    		return writer.toString();
    	}
    
    	public static void printIllegalArgumentException(String tag, String arg) {
    		if (DEBUG) {
    			final Throwable throwable = new IllegalArgumentException(arg);
    			Log.w(tag, arg, throwable);
    		}
    	}
    
    }
    
    package com.fp.app.readbinder;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.Parcel;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class IPCSyncActivity extends Activity implements OnClickListener {
    	@Override
    	protected void onDestroy() {
    		super.unbindService(mConnection);
    		super.unbindService(mConnection2);
    		super.onDestroy();
    	}
    
    	private static final int BTNTOPMARGIN = 10;
    	private static final int BTNHEIGHT = 50;
    	private static final int BTNWIDTH = 120;
    	private static final String STREXIT = "exit";
    	private static final String STRBINDSERVICE1 = "bind service connection 1";
    	private static final String STRBINDSERVICE2 = "bind service connection 2";
    	private static final int EXIT = 104;
    	private static final int BINDSERVICE = 102;
    	private static final int STARTSERVICE = 101;
    	private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    	private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
    	private Button btnBindService1, btnBindService2, btnExit;
    	public TextView headerText;
    	private IBinder mBinder1, mBinder2;
    
    	public void onCreate(Bundle icicle) {
    		super.onCreate(icicle);
    		LinearLayout layout = new LinearLayout(this);
    		layout.setOrientation(LinearLayout.VERTICAL);
    		setView(layout);
    		String tna = Thread.currentThread().getName();
    		Thread.currentThread().setName(tna + "-ac01");
    		bindService();
    	}
    
    	private void bindService() {
    		bindService(new Intent("com.fp.app.service.myService"), mConnection, Context.BIND_AUTO_CREATE);
    		bindService(new Intent("com.fp.app.service.myService"), mConnection2, Context.BIND_AUTO_CREATE);
    	}
    
    	private void setView(LinearLayout layout) {
    		setBtn(layout, btnBindService1, STRBINDSERVICE1, STARTSERVICE);
    		setBtn(layout, btnBindService2, STRBINDSERVICE2, BINDSERVICE);
    		setBtn(layout, btnExit, STREXIT, EXIT);
    		setTv(layout);
    
    	}
    
    	private void setBtn(LinearLayout layout, Button btn, String text, int resId) {
    		btn = new Button(this);
    		btn.setId(resId);
    		btn.setText(text);
    		btn.setBackgroundResource(R.drawable.music_play);
    		btn.setOnClickListener(this);
    		layout.addView(btn, getPara());
    	}
    
    	private void setTv(LinearLayout layout) {
    		headerText = new TextView(this);
    		headerText.setTextColor(Color.WHITE);
    		headerText.setText("");
    		LinearLayout.LayoutParams tvParam = new LinearLayout.LayoutParams(FP, WC);
    		tvParam.topMargin = BTNTOPMARGIN;
    		layout.addView(headerText, tvParam);
    		setContentView(layout);
    	}
    
    	private LinearLayout.LayoutParams getPara() {
    		LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(BTNWIDTH, BTNHEIGHT);
    		param.topMargin = BTNTOPMARGIN;
    		return param;
    	}
    
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case STARTSERVICE:
    			onTransaction1();
    			break;
    		case BINDSERVICE:
    			onTransaction2();
    			break;
    		case EXIT:
    			finish();
    			break;
    		}
    	}
    
    	private ServiceConnection mConnection = new ServiceConnection() {
    		public void onServiceConnected(ComponentName className, IBinder ibinder) {
    			mBinder1 = ibinder;
    		}
    
    		public void onServiceDisconnected(ComponentName className) {
    		}
    	};
    	private ServiceConnection mConnection2 = new ServiceConnection() {
    		public void onServiceConnected(ComponentName className, IBinder ibinder) {
    			mBinder2 = ibinder;
    		}
    
    		public void onServiceDisconnected(ComponentName className) {
    		}
    	};
    
    	private void onTransaction2() {
    		Parcel pc = Parcel.obtain();
    		Parcel pc_reply = Parcel.obtain();
    		try {
    			mBinder2.transact(1, pc, pc_reply, 0);
    			headerText.setText(pc_reply.readString());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	private void onTransaction1() {
    		Parcel p = Parcel.obtain();
    		Parcel p_reply = Parcel.obtain();
    		try {
    			mBinder1.transact(0, p, p_reply, 0);
    			headerText.setText(p_reply.readString());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    package com.fp.app.readbinder;
    
    import com.fp.app.debug.DebugLog;
    
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.Parcel;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class mainActivity extends Activity implements OnClickListener {
    	@Override
    	protected void onDestroy() {
    		super.unbindService(mConnection);
    		super.onDestroy();
    	}
    
    	private static final int BTNTOPMARGIN = 10;
    	private static final int BTNHEIGHT = 50;
    	private static final int BTNWIDTH = 120;
    	private static final String STRIPCSYNC = "transfer to ipc sync";
    	private static final String STREXIT = "exit";
    	private static final String STRIPCCALL = "ipc call";
    	private static final String STRBINDSERVICE = "bind service";
    	private static final String STRSTARTSERVICE = "start service";
    	private static final int IPCSYNC = 105;
    	private static final int EXIT = 104;
    	private static final int IPCCALL = 103;
    	private static final int BINDSERVICE = 102;
    	private static final int STARTSERVICE = 101;
    	private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    	private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
    	private Button btnStartService, btnBindService, btnIPCCall, btnExit,btnTransferTOIPCSync;
    	public TextView headerText;
    	private IBinder mBinder = null;
    
    	public void onCreate(Bundle icicle) {
    		super.onCreate(icicle);
    		LinearLayout layout = new LinearLayout(this);
    		layout.setOrientation(LinearLayout.VERTICAL);
    		setView(layout);
    		String tna = Thread.currentThread().getName();
    		Thread.currentThread().setName(tna + "-ac01");
    	}
    
    	private void setView(LinearLayout layout) {
    		setBtn(layout, btnStartService, STRSTARTSERVICE, STARTSERVICE);
    		setBtn(layout, btnBindService, STRBINDSERVICE, BINDSERVICE);
    		setBtn(layout, btnIPCCall, STRIPCCALL, IPCCALL);
    		setBtn(layout, btnExit, STREXIT, EXIT);
    		setBtn(layout, btnTransferTOIPCSync, STRIPCSYNC, IPCSYNC);
    		setTv(layout);
    
    	}
    
    	private void setBtn(LinearLayout layout, Button btn, String text, int resId) {
    		btn = new Button(this);
    		btn.setId(resId);
    		btn.setText(text);
    		btn.setBackgroundResource(R.drawable.music_play);
    		btn.setOnClickListener(this);
    		layout.addView(btn, getPara());
    	}
    
    	private void setTv(LinearLayout layout) {
    		headerText = new TextView(this);
    		headerText.setTextColor(Color.WHITE);
    		headerText.setText("");
    		LinearLayout.LayoutParams tvParam = new LinearLayout.LayoutParams(FP, WC);
    		tvParam.topMargin = BTNTOPMARGIN;
    		layout.addView(headerText, tvParam);
    		setContentView(layout);
    	}
    
    	private LinearLayout.LayoutParams getPara() {
    		LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(BTNWIDTH, BTNHEIGHT);
    		param.topMargin = BTNTOPMARGIN;
    		return param;
    	}
    
    	private ServiceConnection mConnection = new ServiceConnection() {
    		public void onServiceConnected(ComponentName className, IBinder ibinder) {
    			mBinder = ibinder;
    		}
    
    		public void onServiceDisconnected(ComponentName className) {
    		}
    	};
    
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case STARTSERVICE:
    			startService();
    			break;
    		case BINDSERVICE:
    			bindService();
    			break;
    		case IPCCALL:
    			transact();
    			break;
    		case EXIT:
    			finish();
    			break;
    		case IPCSYNC:
    			transfer();
    			break;
    		}
    	}
    
    	private void transfer() {
    		Intent targetIntent = new Intent(this, IPCSyncActivity.class);
    		startActivity(targetIntent);
    	}
    
    	private void transact() {
    		DebugLog.printTrace("transact");
    		Parcel pc = Parcel.obtain();
    		pc.writeString("budoudou");
    		Parcel pc_reply = Parcel.obtain();
    		try {
    			mBinder.transact(1, pc, pc_reply, 0);
    			headerText.setText(pc_reply.readString());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	private void bindService() {
    		bindService(new Intent("com.fp.app.service.FPService"), mConnection, Context.BIND_AUTO_CREATE);
    		DebugLog.printTrace("bindService");
    	}
    
    	private void startService() {
    		startService(new Intent("com.fp.app.service.FPService"));
    		DebugLog.printTrace("startService");
    	}
    }
    
    package com.fp.app.readbinder;
    
    import com.fp.app.debug.DebugLog;
    
    import android.app.Activity;
    import android.graphics.Color;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class subActivity extends Activity implements OnClickListener {
    	private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    	private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
    	private Button btn;
    	public TextView tv;
    
    	public void onCreate(Bundle icicle) {
    		super.onCreate(icicle);
    		LinearLayout layout = new LinearLayout(this);
    		layout.setOrientation(LinearLayout.VERTICAL);
    		setBtn(layout);
    		setTV(layout);
    	}
    
    	private void setTV(LinearLayout layout) {
    		tv = new TextView(this);
    		tv.setTextColor(Color.WHITE);
    		tv.setText("");
    		LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
    		param2.topMargin = 10;
    		layout.addView(tv, param2);
    		setContentView(layout);
    		DebugLog.printTrace("onCreate");
    		tv.setText(Thread.currentThread().getName() + "-myActivity");
    	}
    
    	private void setBtn(LinearLayout layout) {
    		btn = new Button(this);
    		btn.setId(101);
    		btn.setText("exit");
    		btn.setBackgroundResource(R.drawable.music_play);
    		btn.setOnClickListener(this);
    		LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(120, 50);
    		param.topMargin = 10;
    		layout.addView(btn, param);
    	}
    
    	public void onClick(View v) {
    		switch (v.getId()) {
    		case 101:
    			finish();
    			break;
    		}
    	}
    }
    
    package com.fp.app.service;
    
    import com.fp.app.debug.DebugLog;
    import com.fp.app.readbinder.subActivity;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.os.Parcel;
    
    public class FPService extends Service {
    	private IBinder mBinder = null;
    
    	@Override
    	public void onCreate() {
    		Thread.currentThread().setName(Thread.currentThread().getName() + "-onCreate");
    		mBinder = new myBinder();
    		DebugLog.printTrace("service onCreate");
    	}
    
    	@Override
    	public void onStart(Intent intent, int startId) {
    		Thread.currentThread().setName(Thread.currentThread().getName() + "-onStart");
    		Intent i = new Intent(getApplicationContext(), subActivity.class);
    		i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    		getApplicationContext().startActivity(i);
    		DebugLog.printTrace("service onStart");
    	}
    
    	@Override
    	public IBinder onBind(Intent intent) {
    		Thread.currentThread().setName(Thread.currentThread().getName() + "-onBind");
    		Intent in = new Intent(this.getApplicationContext(), subActivity.class);
    		in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    		startActivity(in);
    		DebugLog.printTrace("service onBind");
    		return mBinder;
    	}
    
    	public class myBinder extends Binder {
    
    		public myBinder() {
    			Thread.currentThread().setName(Thread.currentThread().getName() + "-myBinder");
    		}
    
    		@Override
    		public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {
    			DebugLog.log(data.readString());
    			reply.writeString(Thread.currentThread().getName());		
    			DebugLog.printTrace("onTransact");
    			return true;
    		}
    	}
    }
    
    package com.fp.app.service;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.Binder;
    import android.os.IBinder;
    import android.os.Parcel;
    
    public class myService extends Service {
    	private static int count = 0;
    
    	public IBinder onBind(Intent intent) {
    		count++;
    		return new myBinder();
    	}
    
    	public class myBinder extends Binder {
    		private int value = 0;
    
    
    		public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws android.os.RemoteException {
    			if (code == 0) {
    				value += 5;
    				try {
    					Thread.sleep(8000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    			} else if (code == 1)
    				value += 300;
    			reply.writeString(" count:" + String.valueOf(count) + " value:" + String.valueOf(value));
    			return true;
    		}
    	}
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    	package="com.fp.app.readbinder">
    	<application android:icon="@drawable/icon">
    		<activity android:name=".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=".IPCSyncActivity" />
    		<activity android:name=".subActivity" android:process=":remote">
    		</activity>
    		<service android:name="com.fp.app.service.FPService" android:process=":remote">
    			<intent-filter>
    				<action android:name="com.fp.app.service.FPService" />
    			</intent-filter>
    		</service>
    	   <service android:name="com.fp.app.service.myService" android:process=":remote">
    			<intent-filter>
    				<action android:name="com.fp.app.service.myService" />
    			</intent-filter>
    		</service>
    
    	</application>
    </manifest>
    

  • 相关阅读:
    Mybatis插件开发入门,运行原理,例子
    ActiveMQ是什么,为什么使用MQ
    sql优化
    用户注册流程
    JMS入门Demo
    运维自动化之Ansible
    ceph安装部署
    ceph工作原理
    linux进程
    任务计划
  • 原文地址:https://www.cnblogs.com/budoudou/p/2103255.html
Copyright © 2020-2023  润新知