目录
7、 短程通信 vs. 远程通信
範例: 短程通信
撰写步骤
範例: 遠程通信
7、 短程通信 vs. 远程通信
範例: 短程通信
- 首先出现ac01画面,立即启动myService,定时连续传来数字,如下:
- 由于定时连续传来数字,所以数字会持续递增,如下 :
// AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.misoo.pkm"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".ac01“
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".myService" > </service>
</application>
</manifest>
- 这AndroidManifest.xml指定了: ac01和myService是在同一进程里执行。
撰写步骤
Step-1: 定义 IListener接口:
// IListener.java
package com.misoo.ppvv;
public interface IListener {
public void update(String s);
}
// ac01.java
// …….
public class ac01 extends Activity implements OnClickListener {
private final int WC =
LinearLayout.LayoutParams.WRAP_CONTENT;
private TextView tx;
private Button btn;
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams param =
new LinearLayout.LayoutParams(100, WC);
param.topMargin = 5;
tx = new TextView(this); tx.setTextSize(26);
tx.setTextColor(Color.RED);
tx.setBackgroundResource(R.drawable.x_yellow);
layout.addView(tx, param);
btn = new Button(this); btn.setText("Exit");
btn.setBackgroundResource(R.drawable.earth);
btn.setOnClickListener(this);
layout.addView(btn, param);
this.setContentView(layout);
//------------------------------------------------------------------
myService.setUpdateListener( new UpdateUIListener() );
Intent svc = new Intent(this, myService.class);
startService(svc);
}
@Override protected void onDestroy() {
super.onDestroy();
Intent svc = new Intent(this, myService.class);
stopService(svc);
}
class UpdateUIListener implements IListener {
public void update(String s) tx.setText(" " + s);
}
public void onClick(View v) { this.finish(); }
}
- 诞生一个UpdateUIListner的对象,然后将此对象之参考值(Reference)传递给myService,存于plis参考变量里。
// myService.java
// ……..
public class myService extends Service {
private static IListener plis;
private static int k = 0;
private Timer timer = new Timer();
public Handler handler = new Handler(){
public void handleMessage(Message msg) {
plis.update(String.valueOf(k++));
}
};
@Override public void onCreate() {
super.onCreate();
TimerTask task = new TimerTask() {
@Override public void run() {
handler.sendEmptyMessage(0);
}};
timer.schedule(task,1000, 4000);
}
@Override public IBinder onBind(Intent intent)
{ return null; }
public static void setUpdateListener(IListener listener)
{ plis = listener; }
}
- 接着,诞生一个Intent对象去要求Android启动myService。就执行到myService的onCreate()函数。
- 此onCreate()函数诞生一个Timer对象,它会定时呼叫Handler类别的handleMessage()函数。
- 此onCreate()函数就透过plis而将数据传递给ac01里的UpdateUIListner对象,然后将数字呈现于画面上,并且循环下去。
// AndroidManifest.xml
//……..
<service android:name=".myService" android:process=":remote" >
<intent-filter>
<action android:name
="com.misoo.pkm.REMOTE_SERVICE" />
</intent-filter></service>
</manifest>
範例: 遠程通信
- 兹拿刚才的MP3播放范例,来说明其详细步骤。 Activity类想跨进程去调用MediaPlayer播放引擎,如下图所示:
// myActivity.java
// ……..
public class myActivity extends Activity implements OnClickListener
{
private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
private Button btn, btn2, btn3;
public TextView tv;
private IBinder ib = null;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this); btn.setId(101); btn.setText("play");
btn.setBackgroundResource(R.drawable.heart);
btn.setOnClickListener(this);
LinearLayout.LayoutParams param = new
LinearLayout.LayoutParams(80, 50);
param.topMargin = 10;
layout.addView(btn, param);
btn2 = new Button(this); btn2.setId(102); btn2.setText("stop");
btn2.setBackgroundResource(R.drawable.heart);
btn2.setOnClickListener(this);
layout.addView(btn2, param);
btn3 = new Button(this); btn3.setId(103); btn3.setText("exit");
btn3.setBackgroundResource(R.drawable.heart);
btn3.setOnClickListener(this);
layout.addView(btn3, param);
tv = new TextView(this); tv.setTextColor(Color.WHITE);
tv.setText("Ready");
LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
param2.topMargin = 10;
layout.addView(tv, param2);
setContentView(layout);
//-------------------------------------------------------------------------------
// startService(…)
bindService(new Intent("com.misoo.kx02c.REMOTE_SERVICE"),
mConnection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName,className, IBinder ibinder) {
ib = ibinder;
}
public void onServiceDisconnected(ComponentName,className) {}
};
public void onClick(View v) {
switch (v.getId()) {
case 101:
Parcel pc = Parcel.obtain();
Parcel pc_reply = Parcel.obtain();
pc.writeString("playing");
try {
ib.transact(1, pc, pc_reply, 0);
tv.setText(pc_reply.readString());
} catch (Exception e) { e.printStackTrace(); } break;
case 102:
pc = Parcel.obtain(); pc_reply = Parcel.obtain();
pc.writeString("stop");
try { ib.transact(2, pc, pc_reply, 0);
tv.setText(pc_reply.readString());
} catch (Exception e) { e.printStackTrace(); }
break;
case 103: finish(); break;
}}}
- App启动时(就会把App的 load到内存里,此刻通称为loading-time。在这个时刻,就会创建了mConnection对象。
- 因为mConnection对象不是属于特定函数内的对象,而是属于类的对象,各函数都可用的公用对象。这种static对象(或变量)都是loading-time就创建了。
- App被load进来之后,才会启动(创建)myActivity对象,之后才会调用myActivity的onCreate()函数。
// myService.java
// …….
public class myService extends Service {
private IBinder mBinder = null;
@Override public void onCreate() {
mBinder = new myBinder(getApplicationContext());
}
@Override public IBinder onBind(Intent intent) {
return mBinder;
}
}
// myBinder.java
// ……..
public class myBinder extends Binder{
private MediaPlayer mPlayer = null;
private Context ctx;
public myBinder(Context cx)
{ ctx= cx; }
@Override public boolean onTransact(int code,Parcel data, Parcel reply, int flags)
throws android.os.RemoteException
{
reply.writeString(data.readString()+ " mp3");
if(code == 1)
this.play();
else if(code == 2)
this.stop();
return true;
}
public void play(){
if(mPlayer != null) return;
mPlayer = MediaPlayer.create(ctx, R.raw.test_cbr);
try { mPlayer.start();
}catch (Exception e)
{ Log.e("StartPlay", "error: " + e.getMessage(), e);}
}
public void stop(){
if (mPlayer != null) {
mPlayer.stop(); mPlayer.release(); mPlayer = null;
}
}
}